Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 4 pull requests #112470

Closed
wants to merge 11 commits into from
Closed
150 changes: 77 additions & 73 deletions compiler/rustc_borrowck/src/region_infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
pub(crate) fn infer_opaque_types(
&self,
infcx: &InferCtxt<'tcx>,
opaque_ty_decls: FxIndexMap<OpaqueTypeKey<'tcx>, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>,
opaque_ty_decls: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
) -> FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> {
let mut result: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> = FxIndexMap::default();

Expand All @@ -72,7 +72,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
.collect();
debug!(?member_constraints);

for (opaque_type_key, (concrete_type, origin)) in opaque_ty_decls {
for (opaque_type_key, concrete_type) in opaque_ty_decls {
let substs = opaque_type_key.substs;
debug!(?concrete_type, ?substs);

Expand Down Expand Up @@ -143,7 +143,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let ty = infcx.infer_opaque_definition_from_instantiation(
opaque_type_key,
universal_concrete_type,
origin,
);
// Sometimes two opaque types are the same only after we remap the generic parameters
// back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to `(X, Y)`
Expand Down Expand Up @@ -215,7 +214,6 @@ pub trait InferCtxtExt<'tcx> {
&self,
opaque_type_key: OpaqueTypeKey<'tcx>,
instantiated_ty: OpaqueHiddenType<'tcx>,
origin: OpaqueTyOrigin,
) -> Ty<'tcx>;
}

Expand Down Expand Up @@ -248,109 +246,115 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
&self,
opaque_type_key: OpaqueTypeKey<'tcx>,
instantiated_ty: OpaqueHiddenType<'tcx>,
origin: OpaqueTyOrigin,
) -> Ty<'tcx> {
if let Some(e) = self.tainted_by_errors() {
return self.tcx.ty_error(e);
}

if let Err(guar) =
check_opaque_type_parameter_valid(self.tcx, opaque_type_key, instantiated_ty.span)
{
return self.tcx.ty_error(guar);
}

let definition_ty = instantiated_ty
.remap_generic_params_to_declaration_params(opaque_type_key, self.tcx, false)
.ty;

if let Err(guar) = check_opaque_type_parameter_valid(
// `definition_ty` does not live in of the current inference context,
// so lets make sure that we don't accidentally misuse our current `infcx`.
match check_opaque_type_well_formed(
self.tcx,
opaque_type_key,
origin,
self.next_trait_solver(),
opaque_type_key.def_id,
instantiated_ty.span,
definition_ty,
) {
return self.tcx.ty_error(guar);
Ok(hidden_ty) => hidden_ty,
Err(guar) => self.tcx.ty_error(guar),
}
}
}

// Only check this for TAIT. RPIT already supports `tests/ui/impl-trait/nested-return-type2.rs`
// on stable and we'd break that.
let OpaqueTyOrigin::TyAlias { .. } = origin else {
return definition_ty;
};
let def_id = opaque_type_key.def_id;
// This logic duplicates most of `check_opaque_meets_bounds`.
// FIXME(oli-obk): Also do region checks here and then consider removing `check_opaque_meets_bounds` entirely.
let param_env = self.tcx.param_env(def_id);
// HACK This bubble is required for this tests to pass:
// nested-return-type2-tait2.rs
// nested-return-type2-tait3.rs
// FIXME(-Ztrait-solver=next): We probably should use `DefiningAnchor::Error`
// and prepopulate this `InferCtxt` with known opaque values, rather than
// using the `Bind` anchor here. For now it's fine.
let infcx = self
.tcx
.infer_ctxt()
.with_opaque_type_inference(if self.next_trait_solver() {
DefiningAnchor::Bind(def_id)
} else {
DefiningAnchor::Bubble
})
.build();
let ocx = ObligationCtxt::new(&infcx);
// Require the hidden type to be well-formed with only the generics of the opaque type.
// Defining use functions may have more bounds than the opaque type, which is ok, as long as the
// hidden type is well formed even without those bounds.
let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into()));

let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id);
/// This logic duplicates most of `check_opaque_meets_bounds`.
/// FIXME(oli-obk): Also do region checks here and then consider removing
/// `check_opaque_meets_bounds` entirely.
fn check_opaque_type_well_formed<'tcx>(
tcx: TyCtxt<'tcx>,
next_trait_solver: bool,
def_id: LocalDefId,
definition_span: Span,
definition_ty: Ty<'tcx>,
) -> Result<Ty<'tcx>, ErrorGuaranteed> {
// Only check this for TAIT. RPIT already supports `tests/ui/impl-trait/nested-return-type2.rs`
// on stable and we'd break that.
let opaque_ty_hir = tcx.hir().expect_item(def_id);
let OpaqueTyOrigin::TyAlias { .. } = opaque_ty_hir.expect_opaque_ty().origin else {
return Ok(definition_ty);
};
let param_env = tcx.param_env(def_id);
// HACK This bubble is required for this tests to pass:
// nested-return-type2-tait2.rs
// nested-return-type2-tait3.rs
// FIXME(-Ztrait-solver=next): We probably should use `DefiningAnchor::Error`
// and prepopulate this `InferCtxt` with known opaque values, rather than
// using the `Bind` anchor here. For now it's fine.
let infcx = tcx
.infer_ctxt()
.with_next_trait_solver(next_trait_solver)
.with_opaque_type_inference(if next_trait_solver {
DefiningAnchor::Bind(def_id)
} else {
DefiningAnchor::Bubble
})
.build();
let ocx = ObligationCtxt::new(&infcx);
let identity_substs = InternalSubsts::identity_for_item(tcx, def_id);

// Require that the hidden type actually fulfills all the bounds of the opaque type, even without
// the bounds that the function supplies.
let opaque_ty = self.tcx.mk_opaque(def_id.to_def_id(), id_substs);
if let Err(err) = ocx.eq(
&ObligationCause::misc(instantiated_ty.span, def_id),
param_env,
opaque_ty,
definition_ty,
) {
// Require that the hidden type actually fulfills all the bounds of the opaque type, even without
// the bounds that the function supplies.
let opaque_ty = tcx.mk_opaque(def_id.to_def_id(), identity_substs);
ocx.eq(&ObligationCause::misc(definition_span, def_id), param_env, opaque_ty, definition_ty)
.map_err(|err| {
infcx
.err_ctxt()
.report_mismatched_types(
&ObligationCause::misc(instantiated_ty.span, def_id),
&ObligationCause::misc(definition_span, def_id),
opaque_ty,
definition_ty,
err,
)
.emit();
}
.emit()
})?;

ocx.register_obligation(Obligation::misc(
infcx.tcx,
instantiated_ty.span,
def_id,
param_env,
predicate,
));
// Require the hidden type to be well-formed with only the generics of the opaque type.
// Defining use functions may have more bounds than the opaque type, which is ok, as long as the
// hidden type is well formed even without those bounds.
let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into()));
ocx.register_obligation(Obligation::misc(tcx, definition_span, def_id, param_env, predicate));

// Check that all obligations are satisfied by the implementation's
// version.
let errors = ocx.select_all_or_error();
// Check that all obligations are satisfied by the implementation's
// version.
let errors = ocx.select_all_or_error();

// This is still required for many(half of the tests in ui/type-alias-impl-trait)
// tests to pass
let _ = infcx.take_opaque_types();
// This is still required for many(half of the tests in ui/type-alias-impl-trait)
// tests to pass
let _ = infcx.take_opaque_types();

if errors.is_empty() {
definition_ty
} else {
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
self.tcx.ty_error(reported)
}
if errors.is_empty() {
Ok(definition_ty)
} else {
Err(infcx.err_ctxt().report_fulfillment_errors(&errors))
}
}

fn check_opaque_type_parameter_valid(
tcx: TyCtxt<'_>,
opaque_type_key: OpaqueTypeKey<'_>,
origin: OpaqueTyOrigin,
span: Span,
) -> Result<(), ErrorGuaranteed> {
match origin {
let opaque_ty_hir = tcx.hir().expect_item(opaque_type_key.def_id);
match opaque_ty_hir.expect_opaque_ty().origin {
// No need to check return position impl trait (RPIT)
// because for type and const parameters they are correct
// by construction: we convert
Expand Down
34 changes: 23 additions & 11 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use std::{fmt, iter, mem};

use either::Either;

use hir::OpaqueTyOrigin;
use rustc_data_structures::frozen::Frozen;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_errors::ErrorGuaranteed;
Expand All @@ -28,6 +27,7 @@ use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::AssertKind;
use rustc_middle::mir::*;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::adjustment::PointerCast;
use rustc_middle::ty::cast::CastTy;
use rustc_middle::ty::subst::{SubstsRef, UserSubsts};
Expand Down Expand Up @@ -241,7 +241,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
hidden_type.ty = infcx.tcx.ty_error(reported);
}

(opaque_type_key, (hidden_type, decl.origin))
(opaque_type_key, hidden_type)
})
.collect();

Expand Down Expand Up @@ -878,8 +878,7 @@ struct BorrowCheckContext<'a, 'tcx> {
pub(crate) struct MirTypeckResults<'tcx> {
pub(crate) constraints: MirTypeckRegionConstraints<'tcx>,
pub(crate) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
pub(crate) opaque_type_values:
FxIndexMap<OpaqueTypeKey<'tcx>, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>,
pub(crate) opaque_type_values: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
}

/// A collection of region constraints that must be satisfied for the
Expand Down Expand Up @@ -1053,15 +1052,28 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
ConstraintCategory::OpaqueType,
CustomTypeOp::new(
|ocx| {
for (key, hidden_ty) in renumbered_opaques {
ocx.register_infer_ok_obligations(
ocx.infcx.register_hidden_type_in_new_solver(
key,
param_env,
hidden_ty.ty,
)?,
let mut obligations = Vec::new();
for (opaque_type_key, hidden_ty) in renumbered_opaques {
let cause = ObligationCause::dummy();
ocx.infcx.insert_hidden_type(
opaque_type_key,
&cause,
param_env,
hidden_ty.ty,
true,
&mut obligations,
)?;

ocx.infcx.add_item_bounds_for_hidden_type(
opaque_type_key,
cause,
param_env,
hidden_ty.ty,
&mut obligations,
);
}

ocx.register_obligations(obligations);
Ok(())
},
"register pre-defined opaques",
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_expand/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,11 @@ pub fn pre_configure_attrs(sess: &Session, attrs: &[Attribute]) -> ast::AttrVec
config_tokens: false,
lint_node_id: ast::CRATE_NODE_ID,
};
let attrs: ast::AttrVec =
attrs.iter().flat_map(|attr| strip_unconfigured.process_cfg_attr(attr)).collect();
if strip_unconfigured.in_cfg(&attrs) { attrs } else { ast::AttrVec::new() }
attrs
.iter()
.flat_map(|attr| strip_unconfigured.process_cfg_attr(attr))
.take_while(|attr| !is_cfg(attr) || strip_unconfigured.cfg_true(attr))
.collect()
}

#[macro_export]
Expand Down
20 changes: 16 additions & 4 deletions compiler/rustc_expand/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1039,7 +1039,12 @@ trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized {
) -> Result<Self::OutputTy, Self> {
Ok(noop_flat_map(node, collector))
}
fn expand_cfg_false(&mut self, collector: &mut InvocationCollector<'_, '_>, span: Span) {
fn expand_cfg_false(
&mut self,
collector: &mut InvocationCollector<'_, '_>,
_pos: usize,
span: Span,
) {
collector.cx.emit_err(RemoveNodeNotSupported { span, descr: Self::descr() });
}

Expand Down Expand Up @@ -1409,8 +1414,15 @@ impl InvocationCollectorNode for ast::Crate {
fn noop_visit<V: MutVisitor>(&mut self, visitor: &mut V) {
noop_visit_crate(self, visitor)
}
fn expand_cfg_false(&mut self, collector: &mut InvocationCollector<'_, '_>, _span: Span) {
self.attrs.clear();
fn expand_cfg_false(
&mut self,
collector: &mut InvocationCollector<'_, '_>,
pos: usize,
_span: Span,
) {
// Attributes above `cfg(FALSE)` are left in place, because we may want to configure
// some global crate properties even on fully unconfigured crates.
self.attrs.truncate(pos);
// Standard prelude imports are left in the crate for backward compatibility.
self.items.truncate(collector.cx.num_standard_library_imports);
}
Expand Down Expand Up @@ -1804,7 +1816,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
continue;
}

node.expand_cfg_false(self, span);
node.expand_cfg_false(self, pos, span);
continue;
}
sym::cfg_attr => {
Expand Down
Loading