Skip to content

Commit

Permalink
Auto merge of #99506 - Dylan-DPC:rollup-q3msucx, r=Dylan-DPC
Browse files Browse the repository at this point in the history
Rollup of 7 pull requests

Successful merges:

 - #98101 (stdlib support for Apple WatchOS)
 - #99345 (Do not allow typeck children items to constrain outer RPITs)
 - #99383 (Formalize defining_use_anchor)
 - #99436 (Add flag to configure `noalias` on `Box<T>`)
 - #99483 (Fix a numerical underflow in tuple wrap suggestion)
 - #99485 (Stop injecting `#[allow(unused_qualifications)]` in generated `derive` implementations)
 - #99486 (Refactor: remove a string comparison between types in `check_str_addition`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jul 20, 2022
2 parents d60d88f + 17a2832 commit 14dbfeb
Show file tree
Hide file tree
Showing 57 changed files with 544 additions and 332 deletions.
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/consumers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use rustc_hir::def_id::LocalDefId;
use rustc_index::vec::IndexVec;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
use rustc_middle::mir::Body;
use rustc_middle::ty::{self, TyCtxt};

Expand Down Expand Up @@ -31,7 +31,7 @@ pub fn get_body_with_borrowck_facts<'tcx>(
def: ty::WithOptConstParam<LocalDefId>,
) -> BodyWithBorrowckFacts<'tcx> {
let (input_body, promoted) = tcx.mir_promoted(def);
tcx.infer_ctxt().with_opaque_type_inference(def.did).enter(|infcx| {
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def.did)).enter(|infcx| {
let input_body: &Body<'_> = &input_body.borrow();
let promoted: &IndexVec<_, _> = &promoted.borrow();
*super::do_mir_borrowck(&infcx, input_body, promoted, true).1.unwrap()
Expand Down
15 changes: 9 additions & 6 deletions compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_index::bit_set::ChunkedBitSet;
use rustc_index::vec::IndexVec;
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt};
use rustc_middle::mir::{
traversal, Body, ClearCrossCrate, Local, Location, Mutability, Operand, Place, PlaceElem,
PlaceRef, VarDebugInfoContents,
Expand Down Expand Up @@ -130,11 +130,14 @@ fn mir_borrowck<'tcx>(
debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id()));
let hir_owner = tcx.hir().local_def_id_to_hir_id(def.did).owner;

let opt_closure_req = tcx.infer_ctxt().with_opaque_type_inference(hir_owner).enter(|infcx| {
let input_body: &Body<'_> = &input_body.borrow();
let promoted: &IndexVec<_, _> = &promoted.borrow();
do_mir_borrowck(&infcx, input_body, promoted, false).0
});
let opt_closure_req = tcx
.infer_ctxt()
.with_opaque_type_inference(DefiningAnchor::Bind(hir_owner))
.enter(|infcx| {
let input_body: &Body<'_> = &input_body.borrow();
let promoted: &IndexVec<_, _> = &promoted.borrow();
do_mir_borrowck(&infcx, input_body, promoted, false).0
});
debug!("mir_borrowck done");

tcx.arena.alloc(opt_closure_req)
Expand Down
102 changes: 54 additions & 48 deletions compiler/rustc_borrowck/src/region_infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use rustc_data_structures::vec_map::VecMap;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::OpaqueTyOrigin;
use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic;
use rustc_infer::infer::InferCtxt;
use rustc_infer::infer::TyCtxtInferExt as _;
use rustc_infer::infer::{DefiningAnchor, InferCtxt};
use rustc_infer::traits::{Obligation, ObligationCause, TraitEngine};
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts};
Expand Down Expand Up @@ -269,59 +269,65 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// 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);
let body_id = self.tcx.local_def_id_to_hir_id(def_id);
self.tcx.infer_ctxt().enter(move |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()))
.to_predicate(infcx.tcx);
let mut fulfillment_cx = <dyn TraitEngine<'tcx>>::new(infcx.tcx);

// Require that the hidden type actually fulfills all the bounds of the opaque type, even without
// the bounds that the function supplies.
match infcx.register_hidden_type(
OpaqueTypeKey { def_id, substs: id_substs },
ObligationCause::misc(instantiated_ty.span, body_id),
param_env,
definition_ty,
origin,
) {
Ok(infer_ok) => {
for obligation in infer_ok.obligations {
fulfillment_cx.register_predicate_obligation(&infcx, obligation);
// HACK This bubble is required for this tests to pass:
// type-alias-impl-trait/issue-67844-nested-opaque.rs
self.tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).enter(
move |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()))
.to_predicate(infcx.tcx);
let mut fulfillment_cx = <dyn TraitEngine<'tcx>>::new(infcx.tcx);

// Require that the hidden type actually fulfills all the bounds of the opaque type, even without
// the bounds that the function supplies.
match infcx.register_hidden_type(
OpaqueTypeKey { def_id, substs: id_substs },
ObligationCause::misc(instantiated_ty.span, body_id),
param_env,
definition_ty,
origin,
) {
Ok(infer_ok) => {
for obligation in infer_ok.obligations {
fulfillment_cx.register_predicate_obligation(&infcx, obligation);
}
}
Err(err) => {
infcx
.report_mismatched_types(
&ObligationCause::misc(instantiated_ty.span, body_id),
self.tcx.mk_opaque(def_id.to_def_id(), id_substs),
definition_ty,
err,
)
.emit();
}
}
Err(err) => {
infcx
.report_mismatched_types(
&ObligationCause::misc(instantiated_ty.span, body_id),
self.tcx.mk_opaque(def_id.to_def_id(), id_substs),
definition_ty,
err,
)
.emit();
}
}

fulfillment_cx.register_predicate_obligation(
&infcx,
Obligation::misc(instantiated_ty.span, body_id, param_env, predicate),
);
fulfillment_cx.register_predicate_obligation(
&infcx,
Obligation::misc(instantiated_ty.span, body_id, param_env, predicate),
);

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

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

if errors.is_empty() {
definition_ty
} else {
infcx.report_fulfillment_errors(&errors, None, false);
self.tcx.ty_error()
}
})
if errors.is_empty() {
definition_ty
} else {
infcx.report_fulfillment_errors(&errors, None, false);
self.tcx.ty_error()
}
},
)
} else {
definition_ty
}
Expand Down
21 changes: 21 additions & 0 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
use rustc_infer::infer::{
InferCtxt, InferOk, LateBoundRegion, LateBoundRegionConversionTime, NllRegionVariableOrigin,
};
use rustc_infer::traits::ObligationCause;
use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::AssertKind;
Expand Down Expand Up @@ -224,6 +225,26 @@ pub(crate) fn type_check<'mir, 'tcx>(
)
.unwrap();
let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
// Check that RPITs are only constrained in their outermost
// function, otherwise report a mismatched types error.
if let OpaqueTyOrigin::FnReturn(parent) | OpaqueTyOrigin::AsyncFn(parent)
= infcx.opaque_ty_origin_unchecked(opaque_type_key.def_id, hidden_type.span)
&& parent.to_def_id() != body.source.def_id()
{
infcx
.report_mismatched_types(
&ObligationCause::misc(
hidden_type.span,
infcx.tcx.hir().local_def_id_to_hir_id(
body.source.def_id().expect_local(),
),
),
infcx.tcx.mk_opaque(opaque_type_key.def_id.to_def_id(), opaque_type_key.substs),
hidden_type.ty,
ty::error::TypeError::Mismatch,
)
.emit();
}
trace!(
"finalized opaque type {:?} to {:#?}",
opaque_type_key,
Expand Down
10 changes: 1 addition & 9 deletions compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -727,16 +727,8 @@ impl<'a> TraitDef<'a> {

let attr = cx.attribute(cx.meta_word(self.span, sym::automatically_derived));
let opt_trait_ref = Some(trait_ref);
let unused_qual = {
let word = rustc_ast::attr::mk_nested_word_item(Ident::new(
sym::unused_qualifications,
self.span,
));
let list = rustc_ast::attr::mk_list_item(Ident::new(sym::allow, self.span), vec![word]);
cx.attribute(list)
};

let mut a = vec![attr, unused_qual];
let mut a = vec![attr];
a.extend(self.attributes.iter().cloned());

cx.item(
Expand Down
32 changes: 25 additions & 7 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,17 +239,31 @@ impl<'tcx> InferCtxtInner<'tcx> {
}
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum DefiningAnchor {
/// `DefId` of the item.
Bind(LocalDefId),
/// When opaque types are not resolved, we `Bubble` up, meaning
/// return the opaque/hidden type pair from query, for caller of query to handle it.
Bubble,
/// Used to catch type mismatch errors when handling opaque types.
Error,
}

pub struct InferCtxt<'a, 'tcx> {
pub tcx: TyCtxt<'tcx>,

/// The `DefId` of the item in whose context we are performing inference or typeck.
/// It is used to check whether an opaque type use is a defining use.
///
/// If it is `None`, we can't resolve opaque types here and need to bubble up
/// If it is `DefiningAnchor::Bubble`, we can't resolve opaque types here and need to bubble up
/// the obligation. This frequently happens for
/// short lived InferCtxt within queries. The opaque type obligations are forwarded
/// to the outside until the end up in an `InferCtxt` for typeck or borrowck.
pub defining_use_anchor: Option<LocalDefId>,
///
/// It is default value is `DefiningAnchor::Error`, this way it is easier to catch errors that
/// might come up during inference or typeck.
pub defining_use_anchor: DefiningAnchor,

/// During type-checking/inference of a body, `in_progress_typeck_results`
/// contains a reference to the typeck results being built up, which are
Expand Down Expand Up @@ -526,7 +540,7 @@ impl<'tcx> fmt::Display for FixupError<'tcx> {
pub struct InferCtxtBuilder<'tcx> {
tcx: TyCtxt<'tcx>,
fresh_typeck_results: Option<RefCell<ty::TypeckResults<'tcx>>>,
defining_use_anchor: Option<LocalDefId>,
defining_use_anchor: DefiningAnchor,
}

pub trait TyCtxtInferExt<'tcx> {
Expand All @@ -535,7 +549,11 @@ pub trait TyCtxtInferExt<'tcx> {

impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> {
InferCtxtBuilder { tcx: self, defining_use_anchor: None, fresh_typeck_results: None }
InferCtxtBuilder {
tcx: self,
defining_use_anchor: DefiningAnchor::Error,
fresh_typeck_results: None,
}
}
}

Expand All @@ -545,7 +563,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
/// Will also change the scope for opaque type defining use checks to the given owner.
pub fn with_fresh_in_progress_typeck_results(mut self, table_owner: LocalDefId) -> Self {
self.fresh_typeck_results = Some(RefCell::new(ty::TypeckResults::new(table_owner)));
self.with_opaque_type_inference(table_owner)
self.with_opaque_type_inference(DefiningAnchor::Bind(table_owner))
}

/// Whenever the `InferCtxt` should be able to handle defining uses of opaque types,
Expand All @@ -554,8 +572,8 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
/// It is only meant to be called in two places, for typeck
/// (via `with_fresh_in_progress_typeck_results`) and for the inference context used
/// in mir borrowck.
pub fn with_opaque_type_inference(mut self, defining_use_anchor: LocalDefId) -> Self {
self.defining_use_anchor = Some(defining_use_anchor);
pub fn with_opaque_type_inference(mut self, defining_use_anchor: DefiningAnchor) -> Self {
self.defining_use_anchor = defining_use_anchor;
self
}

Expand Down
Loading

0 comments on commit 14dbfeb

Please sign in to comment.