1
Fork 0

don't normalize in astconv

We delay projection normalization to further stages in order to
register user type annotations before normalization in HIR typeck.

There are two consumers of astconv: ItemCtxt and FnCtxt.
The former already expects unnormalized types from astconv, see its
AstConv trait impl.
The latter needs `RawTy` for a cleaner interface.

Unfortunately astconv still needs the normalization machinery in
order to resolve enum variants that have projections in the self type,
e.g. `<<T as Trait>::Assoc>::StructVariant {}`.
This is why `AstConv::normalize_ty_2` is necessary.
This commit is contained in:
Ali MJ Al-Nasrawy 2022-09-17 21:35:47 +03:00
parent 93bf84c902
commit d227506683
25 changed files with 376 additions and 257 deletions

View file

@ -106,11 +106,9 @@ pub trait AstConv<'tcx> {
poly_trait_ref: ty::PolyTraitRef<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>,
) -> Ty<'tcx>; ) -> Ty<'tcx>;
/// Normalize an associated type coming from the user. fn normalize_ty_2(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
/// ty
/// This should only be used by astconv. Use `FnCtxt::normalize` }
/// or `ObligationCtxt::normalize` in downstream crates.
fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>;
/// Invoked when we encounter an error from some prior pass /// Invoked when we encounter an error from some prior pass
/// (e.g., resolve) that is translated into a ty-error. This is /// (e.g., resolve) that is translated into a ty-error. This is
@ -485,14 +483,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// Avoid ICE #86756 when type error recovery goes awry. // Avoid ICE #86756 when type error recovery goes awry.
return tcx.ty_error().into(); return tcx.ty_error().into();
} }
self.astconv tcx.at(self.span).bound_type_of(param.def_id).subst(tcx, substs).into()
.normalize_ty(
self.span,
tcx.at(self.span)
.bound_type_of(param.def_id)
.subst(tcx, substs),
)
.into()
} else if infer_args { } else if infer_args {
self.astconv.ty_infer(Some(param), self.span).into() self.astconv.ty_infer(Some(param), self.span).into()
} else { } else {
@ -1254,7 +1245,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
item_segment: &hir::PathSegment<'_>, item_segment: &hir::PathSegment<'_>,
) -> Ty<'tcx> { ) -> Ty<'tcx> {
let substs = self.ast_path_substs_for_ty(span, did, item_segment); let substs = self.ast_path_substs_for_ty(span, did, item_segment);
self.normalize_ty(span, self.tcx().at(span).bound_type_of(did).subst(self.tcx(), substs)) self.tcx().at(span).bound_type_of(did).subst(self.tcx(), substs)
} }
fn conv_object_ty_poly_trait_ref( fn conv_object_ty_poly_trait_ref(
@ -1786,7 +1777,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
Ok(bound) Ok(bound)
} }
// Create a type from a path to an associated type. // Create a type from a path to an associated type or to an enum variant.
// For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C` // For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C`
// and item_segment is the path segment for `D`. We return a type and a def for // and item_segment is the path segment for `D`. We return a type and a def for
// the whole path. // the whole path.
@ -1814,7 +1805,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// Check if we have an enum variant. // Check if we have an enum variant.
let mut variant_resolution = None; let mut variant_resolution = None;
if let ty::Adt(adt_def, adt_substs) = qself_ty.kind() { if let ty::Adt(adt_def, adt_substs) = self.normalize_ty_2(span, qself_ty).kind() {
if adt_def.is_enum() { if adt_def.is_enum() {
let variant_def = adt_def let variant_def = adt_def
.variants() .variants()
@ -1923,7 +1914,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
adt_substs, adt_substs,
); );
let ty = tcx.bound_type_of(assoc_ty_did).subst(tcx, item_substs); let ty = tcx.bound_type_of(assoc_ty_did).subst(tcx, item_substs);
let ty = self.normalize_ty(span, ty);
return Ok((ty, DefKind::AssocTy, assoc_ty_did)); return Ok((ty, DefKind::AssocTy, assoc_ty_did));
} }
} }
@ -2020,7 +2010,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}; };
let ty = self.projected_ty_from_poly_trait_ref(span, assoc_ty_did, assoc_segment, bound); let ty = self.projected_ty_from_poly_trait_ref(span, assoc_ty_did, assoc_segment, bound);
let ty = self.normalize_ty(span, ty);
if let Some(variant_def_id) = variant_resolution { if let Some(variant_def_id) = variant_resolution {
tcx.struct_span_lint_hir( tcx.struct_span_lint_hir(
@ -2156,7 +2145,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
debug!("qpath_to_ty: trait_ref={:?}", trait_ref); debug!("qpath_to_ty: trait_ref={:?}", trait_ref);
self.normalize_ty(span, tcx.mk_projection(item_def_id, item_substs)) tcx.mk_projection(item_def_id, item_substs)
} }
pub fn prohibit_generics<'a>( pub fn prohibit_generics<'a>(
@ -2417,7 +2406,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
err.note("`impl Trait` types can't have type parameters"); err.note("`impl Trait` types can't have type parameters");
}); });
let substs = self.ast_path_substs_for_ty(span, did, item_segment.0); let substs = self.ast_path_substs_for_ty(span, did, item_segment.0);
self.normalize_ty(span, tcx.mk_opaque(did, substs)) tcx.mk_opaque(did, substs)
} }
Res::Def( Res::Def(
DefKind::Enum DefKind::Enum
@ -2577,7 +2566,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
} }
tcx.ty_error_with_guaranteed(err.emit()) tcx.ty_error_with_guaranteed(err.emit())
} else { } else {
self.normalize_ty(span, ty) ty
} }
} }
Res::Def(DefKind::AssocTy, def_id) => { Res::Def(DefKind::AssocTy, def_id) => {
@ -2720,8 +2709,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
None, None,
ty::BoundConstness::NotConst, ty::BoundConstness::NotConst,
); );
EarlyBinder(self.normalize_ty(span, tcx.at(span).type_of(def_id))) EarlyBinder(tcx.at(span).type_of(def_id)).subst(tcx, substs)
.subst(tcx, substs)
} }
hir::TyKind::Array(ref ty, ref length) => { hir::TyKind::Array(ref ty, ref length) => {
let length = match length { let length = match length {
@ -2731,8 +2719,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
} }
}; };
let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(ty), length)); tcx.mk_ty(ty::Array(self.ast_ty_to_ty(ty), length))
self.normalize_ty(ast_ty.span, array_ty)
} }
hir::TyKind::Typeof(ref e) => { hir::TyKind::Typeof(ref e) => {
let ty_erased = tcx.type_of(e.def_id); let ty_erased = tcx.type_of(e.def_id);

View file

@ -505,11 +505,6 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
} }
} }
fn normalize_ty(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
// Types in item signatures are not normalized to avoid undue dependencies.
ty
}
fn set_tainted_by_errors(&self, _: ErrorGuaranteed) { fn set_tainted_by_errors(&self, _: ErrorGuaranteed) {
// There's no obvious place to track this, so just let it go. // There's no obvious place to track this, so just let it go.
} }

View file

@ -647,14 +647,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
), ),
bound_vars, bound_vars,
); );
// Astconv can't normalize inputs or outputs with escaping bound vars,
// so normalize them here, after we've wrapped them in a binder.
let result = self.normalize(self.tcx.hir().span(hir_id), result);
let c_result = self.inh.infcx.canonicalize_response(result); let c_result = self.inh.infcx.canonicalize_response(result);
self.typeck_results.borrow_mut().user_provided_sigs.insert(expr_def_id, c_result); self.typeck_results.borrow_mut().user_provided_sigs.insert(expr_def_id, c_result);
result // Normalize only after registering in `user_provided_sigs`.
self.normalize(self.tcx.hir().span(hir_id), result)
} }
/// Invoked when we are translating the generator that results /// Invoked when we are translating the generator that results

View file

@ -1,7 +1,7 @@
use crate::callee::{self, DeferredCallResolution}; use crate::callee::{self, DeferredCallResolution};
use crate::method::{self, MethodCallee, SelfSource}; use crate::method::{self, MethodCallee, SelfSource};
use crate::rvalue_scopes; use crate::rvalue_scopes;
use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy}; use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy, RawTy};
use rustc_data_structures::captures::Captures; use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{Applicability, Diagnostic, ErrorGuaranteed, MultiSpan}; use rustc_errors::{Applicability, Diagnostic, ErrorGuaranteed, MultiSpan};
@ -410,23 +410,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
} }
pub fn to_ty(&self, ast_t: &hir::Ty<'_>) -> Ty<'tcx> { pub fn create_raw_ty(&self, span: Span, ty: Ty<'tcx>) -> RawTy<'tcx> {
RawTy { raw: ty, normalized: self.normalize(span, ty) }
}
pub fn to_ty(&self, ast_t: &hir::Ty<'_>) -> RawTy<'tcx> {
let t = <dyn AstConv<'_>>::ast_ty_to_ty(self, ast_t); let t = <dyn AstConv<'_>>::ast_ty_to_ty(self, ast_t);
self.register_wf_obligation(t.into(), ast_t.span, traits::WellFormed(None)); self.register_wf_obligation(t.into(), ast_t.span, traits::WellFormed(None));
t self.create_raw_ty(ast_t.span, t)
} }
pub fn to_ty_saving_user_provided_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { pub fn to_ty_saving_user_provided_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
let ty = self.to_ty(ast_ty); let ty = self.to_ty(ast_ty);
debug!("to_ty_saving_user_provided_ty: ty={:?}", ty); debug!("to_ty_saving_user_provided_ty: ty={:?}", ty);
if Self::can_contain_user_lifetime_bounds(ty) { if Self::can_contain_user_lifetime_bounds(ty.raw) {
let c_ty = self.canonicalize_response(UserType::Ty(ty)); let c_ty = self.canonicalize_response(UserType::Ty(ty.raw));
debug!("to_ty_saving_user_provided_ty: c_ty={:?}", c_ty); debug!("to_ty_saving_user_provided_ty: c_ty={:?}", c_ty);
self.typeck_results.borrow_mut().user_provided_types_mut().insert(ast_ty.hir_id, c_ty); self.typeck_results.borrow_mut().user_provided_types_mut().insert(ast_ty.hir_id, c_ty);
} }
ty ty.normalized
} }
pub fn array_length_to_const(&self, length: &hir::ArrayLen) -> ty::Const<'tcx> { pub fn array_length_to_const(&self, length: &hir::ArrayLen) -> ty::Const<'tcx> {
@ -780,7 +784,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
qpath: &'tcx QPath<'tcx>, qpath: &'tcx QPath<'tcx>,
hir_id: hir::HirId, hir_id: hir::HirId,
span: Span, span: Span,
) -> (Res, Option<Ty<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) { ) -> (Res, Option<RawTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) {
debug!( debug!(
"resolve_ty_and_res_fully_qualified_call: qpath={:?} hir_id={:?} span={:?}", "resolve_ty_and_res_fully_qualified_call: qpath={:?} hir_id={:?} span={:?}",
qpath, hir_id, span qpath, hir_id, span
@ -803,7 +807,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// to be object-safe. // to be object-safe.
// We manually call `register_wf_obligation` in the success path // We manually call `register_wf_obligation` in the success path
// below. // below.
(<dyn AstConv<'_>>::ast_ty_to_ty_in_path(self, qself), qself, segment) let ty = <dyn AstConv<'_>>::ast_ty_to_ty_in_path(self, qself);
(self.create_raw_ty(span, ty), qself, segment)
} }
QPath::LangItem(..) => { QPath::LangItem(..) => {
bug!("`resolve_ty_and_res_fully_qualified_call` called on `LangItem`") bug!("`resolve_ty_and_res_fully_qualified_call` called on `LangItem`")
@ -811,7 +816,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}; };
if let Some(&cached_result) = self.typeck_results.borrow().type_dependent_defs().get(hir_id) if let Some(&cached_result) = self.typeck_results.borrow().type_dependent_defs().get(hir_id)
{ {
self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None)); self.register_wf_obligation(ty.raw.into(), qself.span, traits::WellFormed(None));
// Return directly on cache hit. This is useful to avoid doubly reporting // Return directly on cache hit. This is useful to avoid doubly reporting
// errors with default match binding modes. See #44614. // errors with default match binding modes. See #44614.
let def = cached_result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)); let def = cached_result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id));
@ -819,7 +824,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
let item_name = item_segment.ident; let item_name = item_segment.ident;
let result = self let result = self
.resolve_fully_qualified_call(span, item_name, ty, qself.span, hir_id) .resolve_fully_qualified_call(span, item_name, ty.normalized, qself.span, hir_id)
.or_else(|error| { .or_else(|error| {
let result = match error { let result = match error {
method::MethodError::PrivateMatch(kind, def_id, _) => Ok((kind, def_id)), method::MethodError::PrivateMatch(kind, def_id, _) => Ok((kind, def_id)),
@ -830,13 +835,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// a WF obligation for `dyn MyTrait` when method lookup fails. Otherwise, // a WF obligation for `dyn MyTrait` when method lookup fails. Otherwise,
// register a WF obligation so that we can detect any additional // register a WF obligation so that we can detect any additional
// errors in the self type. // errors in the self type.
if !(matches!(error, method::MethodError::NoMatch(_)) && ty.is_trait()) { if !(matches!(error, method::MethodError::NoMatch(_)) && ty.normalized.is_trait()) {
self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None)); self.register_wf_obligation(
ty.raw.into(),
qself.span,
traits::WellFormed(None),
);
} }
if item_name.name != kw::Empty { if item_name.name != kw::Empty {
if let Some(mut e) = self.report_method_error( if let Some(mut e) = self.report_method_error(
span, span,
ty, ty.normalized,
item_name, item_name,
SelfSource::QPath(qself), SelfSource::QPath(qself),
error, error,
@ -849,7 +858,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}); });
if result.is_ok() { if result.is_ok() {
self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None)); self.register_wf_obligation(ty.raw.into(), qself.span, traits::WellFormed(None));
} }
// Write back the new resolution. // Write back the new resolution.
@ -986,7 +995,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn instantiate_value_path( pub fn instantiate_value_path(
&self, &self,
segments: &[hir::PathSegment<'_>], segments: &[hir::PathSegment<'_>],
self_ty: Option<Ty<'tcx>>, self_ty: Option<RawTy<'tcx>>,
res: Res, res: Res,
span: Span, span: Span,
hir_id: hir::HirId, hir_id: hir::HirId,
@ -996,7 +1005,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let path_segs = match res { let path_segs = match res {
Res::Local(_) | Res::SelfCtor(_) => vec![], Res::Local(_) | Res::SelfCtor(_) => vec![],
Res::Def(kind, def_id) => <dyn AstConv<'_>>::def_ids_for_value_path_segments( Res::Def(kind, def_id) => <dyn AstConv<'_>>::def_ids_for_value_path_segments(
self, segments, self_ty, kind, def_id, self,
segments,
self_ty.map(|ty| ty.normalized),
kind,
def_id,
), ),
_ => bug!("instantiate_value_path on {:?}", res), _ => bug!("instantiate_value_path on {:?}", res),
}; };
@ -1007,8 +1020,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Res::Def(DefKind::Ctor(CtorOf::Variant, _), _) Res::Def(DefKind::Ctor(CtorOf::Variant, _), _)
if let Some(self_ty) = self_ty => if let Some(self_ty) = self_ty =>
{ {
let adt_def = self_ty.ty_adt_def().unwrap(); let adt_def = self_ty.normalized.ty_adt_def().unwrap();
user_self_ty = Some(UserSelfTy { impl_def_id: adt_def.did(), self_ty }); user_self_ty = Some(UserSelfTy { impl_def_id: adt_def.did(), self_ty: self_ty.raw });
is_alias_variant_ctor = true; is_alias_variant_ctor = true;
} }
Res::Def(DefKind::AssocFn | DefKind::AssocConst, def_id) => { Res::Def(DefKind::AssocFn | DefKind::AssocConst, def_id) => {
@ -1027,7 +1040,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// inherent impl, we need to record the // inherent impl, we need to record the
// `T` for posterity (see `UserSelfTy` for // `T` for posterity (see `UserSelfTy` for
// details). // details).
let self_ty = self_ty.expect("UFCS sugared assoc missing Self"); let self_ty = self_ty.expect("UFCS sugared assoc missing Self").raw;
user_self_ty = Some(UserSelfTy { impl_def_id: container_id, self_ty }); user_self_ty = Some(UserSelfTy { impl_def_id: container_id, self_ty });
} }
} }
@ -1109,7 +1122,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.unwrap_or(false); .unwrap_or(false);
let (res, self_ctor_substs) = if let Res::SelfCtor(impl_def_id) = res { let (res, self_ctor_substs) = if let Res::SelfCtor(impl_def_id) = res {
let ty = self.normalize_ty(span, tcx.at(span).type_of(impl_def_id)); let ty = self.normalize_ty_2(span, tcx.at(span).type_of(impl_def_id));
match *ty.kind() { match *ty.kind() {
ty::Adt(adt_def, substs) if adt_def.has_ctor() => { ty::Adt(adt_def, substs) if adt_def.has_ctor() => {
let variant = adt_def.non_enum_variant(); let variant = adt_def.non_enum_variant();
@ -1193,7 +1206,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
<dyn AstConv<'_>>::ast_region_to_region(self.fcx, lt, Some(param)).into() <dyn AstConv<'_>>::ast_region_to_region(self.fcx, lt, Some(param)).into()
} }
(GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
self.fcx.to_ty(ty).into() self.fcx.to_ty(ty).raw.into()
} }
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
self.fcx.const_arg_to_const(&ct.value, param.def_id).into() self.fcx.const_arg_to_const(&ct.value, param.def_id).into()
@ -1227,7 +1240,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// is missing. // is missing.
let default = tcx.bound_type_of(param.def_id); let default = tcx.bound_type_of(param.def_id);
self.fcx self.fcx
.normalize_ty(self.span, default.subst(tcx, substs.unwrap())) .normalize_ty_2(self.span, default.subst(tcx, substs.unwrap()))
.into() .into()
} else { } else {
// If no type arguments were provided, we have to infer them. // If no type arguments were provided, we have to infer them.
@ -1250,13 +1263,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
} }
let substs = self_ctor_substs.unwrap_or_else(|| { let substs_raw = self_ctor_substs.unwrap_or_else(|| {
<dyn AstConv<'_>>::create_substs_for_generic_args( <dyn AstConv<'_>>::create_substs_for_generic_args(
tcx, tcx,
def_id, def_id,
&[], &[],
has_self, has_self,
self_ty, self_ty.map(|s| s.raw),
&arg_count, &arg_count,
&mut CreateCtorSubstsContext { &mut CreateCtorSubstsContext {
fcx: self, fcx: self,
@ -1269,7 +1282,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}); });
// First, store the "user substs" for later. // First, store the "user substs" for later.
self.write_user_type_annotation_from_substs(hir_id, def_id, substs, user_self_ty); self.write_user_type_annotation_from_substs(hir_id, def_id, substs_raw, user_self_ty);
// Normalize only after registering type annotations.
let substs = self.normalize(span, substs_raw);
self.add_required_obligations_for_hir(span, def_id, &substs, hir_id); self.add_required_obligations_for_hir(span, def_id, &substs, hir_id);
@ -1287,6 +1303,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// with the substituted impl type. // with the substituted impl type.
// This also occurs for an enum variant on a type alias. // This also occurs for an enum variant on a type alias.
let impl_ty = self.normalize(span, tcx.bound_type_of(impl_def_id).subst(tcx, substs)); let impl_ty = self.normalize(span, tcx.bound_type_of(impl_def_id).subst(tcx, substs));
let self_ty = self.normalize(span, self_ty);
match self.at(&self.misc(span), self.param_env).eq(impl_ty, self_ty) { match self.at(&self.misc(span), self.param_env).eq(impl_ty, self_ty) {
Ok(ok) => self.register_infer_ok_obligations(ok), Ok(ok) => self.register_infer_ok_obligations(ok),
Err(_) => { Err(_) => {

View file

@ -5,7 +5,7 @@ use crate::method::MethodCallee;
use crate::Expectation::*; use crate::Expectation::*;
use crate::TupleArgumentsFlag::*; use crate::TupleArgumentsFlag::*;
use crate::{ use crate::{
struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy, Needs, struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy, Needs, RawTy,
TupleArgumentsFlag, TupleArgumentsFlag,
}; };
use rustc_ast as ast; use rustc_ast as ast;
@ -1231,13 +1231,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
); );
return None; return None;
} }
Res::Def(DefKind::Variant, _) => match ty.kind() { Res::Def(DefKind::Variant, _) => match ty.normalized.kind() {
ty::Adt(adt, substs) => Some((adt.variant_of_res(def), adt.did(), substs)), ty::Adt(adt, substs) => Some((adt.variant_of_res(def), adt.did(), substs)),
_ => bug!("unexpected type: {:?}", ty), _ => bug!("unexpected type: {:?}", ty.normalized),
}, },
Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _) Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _)
| Res::SelfTyParam { .. } | Res::SelfTyParam { .. }
| Res::SelfTyAlias { .. } => match ty.kind() { | Res::SelfTyAlias { .. } => match ty.normalized.kind() {
ty::Adt(adt, substs) if !adt.is_enum() => { ty::Adt(adt, substs) if !adt.is_enum() => {
Some((adt.non_enum_variant(), adt.did(), substs)) Some((adt.non_enum_variant(), adt.did(), substs))
} }
@ -1248,14 +1248,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Some((variant, did, substs)) = variant { if let Some((variant, did, substs)) = variant {
debug!("check_struct_path: did={:?} substs={:?}", did, substs); debug!("check_struct_path: did={:?} substs={:?}", did, substs);
self.write_user_type_annotation_from_substs(hir_id, did, substs, None);
// FIXME(aliemjay): We're using UserSelfTy unconditionally here because it is the only
// way to register the raw user ty, because `substs` is normalized.
let self_ty = ty::UserSelfTy { impl_def_id: did, self_ty: ty.raw };
self.write_user_type_annotation_from_substs(hir_id, did, substs, Some(self_ty));
// Check bounds on type arguments used in the path. // Check bounds on type arguments used in the path.
self.add_required_obligations_for_hir(path_span, did, substs, hir_id); self.add_required_obligations_for_hir(path_span, did, substs, hir_id);
Some((variant, ty)) Some((variant, ty.normalized))
} else { } else {
match ty.kind() { match ty.normalized.kind() {
ty::Error(_) => { ty::Error(_) => {
// E0071 might be caused by a spelling error, which will have // E0071 might be caused by a spelling error, which will have
// already caused an error message and probably a suggestion // already caused an error message and probably a suggestion
@ -1268,7 +1272,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
path_span, path_span,
E0071, E0071,
"expected struct, variant or union type, found {}", "expected struct, variant or union type, found {}",
ty.sort_string(self.tcx) ty.normalized.sort_string(self.tcx)
) )
.span_label(path_span, "not a struct") .span_label(path_span, "not a struct")
.emit(); .emit();
@ -1656,20 +1660,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
qpath: &QPath<'_>, qpath: &QPath<'_>,
path_span: Span, path_span: Span,
hir_id: hir::HirId, hir_id: hir::HirId,
) -> (Res, Ty<'tcx>) { ) -> (Res, RawTy<'tcx>) {
match *qpath { match *qpath {
QPath::Resolved(ref maybe_qself, ref path) => { QPath::Resolved(ref maybe_qself, ref path) => {
let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself)); let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself).raw);
let ty = <dyn AstConv<'_>>::res_to_ty(self, self_ty, path, true); let ty = <dyn AstConv<'_>>::res_to_ty(self, self_ty, path, true);
(path.res, ty) (path.res, self.create_raw_ty(path_span, ty))
} }
QPath::TypeRelative(ref qself, ref segment) => { QPath::TypeRelative(ref qself, ref segment) => {
let ty = self.to_ty(qself); let ty = self.to_ty(qself);
let result = <dyn AstConv<'_>>::associated_path_to_ty( let result = <dyn AstConv<'_>>::associated_path_to_ty(
self, hir_id, path_span, ty, qself, segment, true, self, hir_id, path_span, ty.raw, qself, segment, true,
); );
let ty = result.map(|(ty, _, _)| ty).unwrap_or_else(|_| self.tcx().ty_error()); let ty = result.map(|(ty, _, _)| ty).unwrap_or_else(|_| self.tcx().ty_error());
let ty = self.create_raw_ty(path_span, ty);
let result = result.map(|(_, kind, def_id)| (kind, def_id)); let result = result.map(|(_, kind, def_id)| (kind, def_id));
// Write back the new resolution. // Write back the new resolution.
@ -1678,7 +1683,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
(result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty) (result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty)
} }
QPath::LangItem(lang_item, span, id) => { QPath::LangItem(lang_item, span, id) => {
self.resolve_lang_item_path(lang_item, span, hir_id, id) let (res, ty) = self.resolve_lang_item_path(lang_item, span, hir_id, id);
(res, self.create_raw_ty(path_span, ty))
} }
} }
} }

View file

@ -17,8 +17,7 @@ use rustc_infer::infer::error_reporting::TypeErrCtxt;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitable};
use rustc_middle::ty::{self, Const, Ty, TyCtxt};
use rustc_session::Session; use rustc_session::Session;
use rustc_span::symbol::Ident; use rustc_span::symbol::Ident;
use rustc_span::{self, Span}; use rustc_span::{self, Span};
@ -298,7 +297,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
self.tcx().mk_projection(item_def_id, item_substs) self.tcx().mk_projection(item_def_id, item_substs)
} }
fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx> { fn normalize_ty_2(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
if ty.has_escaping_bound_vars() { if ty.has_escaping_bound_vars() {
ty // FIXME: normalization and escaping regions ty // FIXME: normalization and escaping regions
} else { } else {
@ -310,7 +309,19 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
self.infcx.set_tainted_by_errors(e) self.infcx.set_tainted_by_errors(e)
} }
fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, _span: Span) { fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span) {
self.write_ty(hir_id, ty) self.write_ty(hir_id, self.normalize_ty_2(span, ty))
} }
} }
/// Represents a user-provided type in the raw form (never normalized).
///
/// This is a bridge between the interface of `AstConv`, which outputs a raw `Ty`,
/// and the API in this module, which expect `Ty` to be fully normalized.
#[derive(Clone, Copy, Debug)]
pub struct RawTy<'tcx> {
pub raw: Ty<'tcx>,
/// The normalized form of `raw`, stored here for efficiency.
pub normalized: Ty<'tcx>,
}

View file

@ -77,7 +77,8 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
Some(ref ty) => { Some(ref ty) => {
let o_ty = self.fcx.to_ty(&ty); let o_ty = self.fcx.to_ty(&ty);
let c_ty = self.fcx.inh.infcx.canonicalize_user_type_annotation(UserType::Ty(o_ty)); let c_ty =
self.fcx.inh.infcx.canonicalize_user_type_annotation(UserType::Ty(o_ty.raw));
debug!("visit_local: ty.hir_id={:?} o_ty={:?} c_ty={:?}", ty.hir_id, o_ty, c_ty); debug!("visit_local: ty.hir_id={:?} o_ty={:?} c_ty={:?}", ty.hir_id, o_ty, c_ty);
self.fcx self.fcx
.typeck_results .typeck_results
@ -85,7 +86,7 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
.user_provided_types_mut() .user_provided_types_mut()
.insert(ty.hir_id, c_ty); .insert(ty.hir_id, c_ty);
Some(LocalTy { decl_ty: o_ty, revealed_ty: o_ty }) Some(LocalTy { decl_ty: o_ty.normalized, revealed_ty: o_ty.normalized })
} }
None => None, None => None,
}; };

View file

@ -297,7 +297,7 @@ fn typeck_with_fallback<'tcx>(
fcx.resolve_generator_interiors(def_id.to_def_id()); fcx.resolve_generator_interiors(def_id.to_def_id());
for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) { for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) {
let ty = fcx.normalize_ty(span, ty); let ty = fcx.normalize(span, ty);
fcx.require_type_is_sized(ty, span, code); fcx.require_type_is_sized(ty, span, code);
} }

View file

@ -372,7 +372,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
.into() .into()
} }
(GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
self.cfcx.to_ty(ty).into() self.cfcx.to_ty(ty).raw.into()
} }
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
self.cfcx.const_arg_to_const(&ct.value, param.def_id).into() self.cfcx.const_arg_to_const(&ct.value, param.def_id).into()
@ -397,7 +397,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
self.cfcx.var_for_def(self.cfcx.span, param) self.cfcx.var_for_def(self.cfcx.span, param)
} }
} }
<dyn AstConv<'_>>::create_substs_for_generic_args( let substs = <dyn AstConv<'_>>::create_substs_for_generic_args(
self.tcx, self.tcx,
pick.item.def_id, pick.item.def_id,
parent_substs, parent_substs,
@ -405,7 +405,9 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
None, None,
&arg_count_correct, &arg_count_correct,
&mut MethodSubstsCtxt { cfcx: self, pick, seg }, &mut MethodSubstsCtxt { cfcx: self, pick, seg },
) );
// FIXME(aliemjay): Type annotation should be registered before normalization.
self.normalize(self.span, substs)
} }
fn unify_receivers( fn unify_receivers(

View file

@ -1,4 +1,4 @@
use crate::FnCtxt; use crate::{FnCtxt, RawTy};
use rustc_ast as ast; use rustc_ast as ast;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{ use rustc_errors::{
@ -842,7 +842,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self, &self,
pat: &Pat<'tcx>, pat: &Pat<'tcx>,
qpath: &hir::QPath<'_>, qpath: &hir::QPath<'_>,
path_resolution: (Res, Option<Ty<'tcx>>, &'tcx [hir::PathSegment<'tcx>]), path_resolution: (Res, Option<RawTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]),
expected: Ty<'tcx>, expected: Ty<'tcx>,
ti: TopInfo<'tcx>, ti: TopInfo<'tcx>,
) -> Ty<'tcx> { ) -> Ty<'tcx> {

View file

@ -91,6 +91,7 @@ pub fn type_op_ascribe_user_type_with_span<'tcx>(
} }
if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty { if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty {
let self_ty = ocx.normalize(&cause, param_env, self_ty);
let impl_self_ty = tcx.bound_type_of(impl_def_id).subst(tcx, substs); let impl_self_ty = tcx.bound_type_of(impl_def_id).subst(tcx, substs);
let impl_self_ty = ocx.normalize(&cause, param_env, impl_self_ty); let impl_self_ty = ocx.normalize(&cause, param_env, impl_self_ty);

View file

@ -1,4 +1,8 @@
// check-pass //~ ERROR broken MIR
// known-bug
// failure-status: 101
// rustc-env: RUSTC_BACKTRACE=0
#![feature(adt_const_params, generic_const_exprs)] #![feature(adt_const_params, generic_const_exprs)]
#![allow(incomplete_features)] #![allow(incomplete_features)]

View file

@ -14,14 +14,6 @@ fn foo<T>() {
let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| (); let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
//~^ ERROR `T` does not live long enough //~^ ERROR `T` does not live long enough
//~| ERROR `T` does not live long enough //~| ERROR `T` does not live long enough
//~| ERROR `T` does not live long enough
//~| ERROR `T` does not live long enough
//~| ERROR `T` does not live long enough
//~| ERROR `T` does not live long enough
//~| ERROR `T` does not live long enough
//~| ERROR `T` does not live long enough
//~| ERROR `T` may not live long enough
//~| ERROR `T` may not live long enough
// //
// FIXME: This error is bogus, but it arises because we try to validate // FIXME: This error is bogus, but it arises because we try to validate
// that `<() as Foo<T>>::Type<'a>` is valid, which requires proving // that `<() as Foo<T>>::Type<'a>` is valid, which requires proving

View file

@ -10,64 +10,5 @@ error: `T` does not live long enough
LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| (); LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `T` does not live long enough error: aborting due to 2 previous errors
--> $DIR/issue-91139.rs:14:12
|
LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `T` does not live long enough
--> $DIR/issue-91139.rs:14:12
|
LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/issue-91139.rs:14:58
|
LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
| ^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn foo<T: 'static>() {
| +++++++++
error: `T` does not live long enough
--> $DIR/issue-91139.rs:14:58
|
LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
| ^^^^^^^^^
error: `T` does not live long enough
--> $DIR/issue-91139.rs:14:58
|
LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
| ^^^^^^^^^
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/issue-91139.rs:14:58
|
LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
| ^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn foo<T: 'static>() {
| +++++++++
error: `T` does not live long enough
--> $DIR/issue-91139.rs:14:58
|
LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
| ^^^^^^^^^
error: `T` does not live long enough
--> $DIR/issue-91139.rs:14:58
|
LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
| ^^^^^^^^^
error: aborting due to 10 previous errors
For more information about this error, try `rustc --explain E0310`.

View file

@ -7,6 +7,7 @@ trait SomeTrait<'a> {
fn give_me_ice<T>() { fn give_me_ice<T>() {
callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>(); callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>();
//~^ ERROR the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied [E0277] //~^ ERROR the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied [E0277]
//~| ERROR the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied [E0277]
} }
fn callee<T: Fn<(&'static (),)>>() { fn callee<T: Fn<(&'static (),)>>() {

View file

@ -1,3 +1,14 @@
error[E0277]: the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied
--> $DIR/issue-85455.rs:8:14
|
LL | callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> SomeTrait<'a>` is not implemented for `T`
|
help: consider restricting type parameter `T`
|
LL | fn give_me_ice<T: for<'a> SomeTrait<'a>>() {
| +++++++++++++++++++++++
error[E0277]: the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied error[E0277]: the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied
--> $DIR/issue-85455.rs:8:5 --> $DIR/issue-85455.rs:8:5
| |
@ -9,6 +20,6 @@ help: consider restricting type parameter `T`
LL | fn give_me_ice<T: for<'a> SomeTrait<'a>>() { LL | fn give_me_ice<T: for<'a> SomeTrait<'a>>() {
| +++++++++++++++++++++++ | +++++++++++++++++++++++
error: aborting due to previous error error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`. For more information about this error, try `rustc --explain E0277`.

View file

@ -16,16 +16,6 @@ impl Trait for &'static () {
fn main() { fn main() {
let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {}; let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
//~^ ERROR lifetime may not live long enough //~^ ERROR implementation of `Trait` is not general enough
//~| ERROR higher-ranked subtype error
//~| ERROR higher-ranked subtype error
//~| ERROR implementation of `Trait` is not general enough
//~| ERROR implementation of `Trait` is not general enough
//~| ERROR implementation of `Trait` is not general enough
//~| ERROR implementation of `Trait` is not general enough
//~| ERROR implementation of `Trait` is not general enough
//~| ERROR implementation of `Trait` is not general enough
//~| ERROR implementation of `Trait` is not general enough
//~| ERROR implementation of `Trait` is not general enough
//~| ERROR implementation of `Trait` is not general enough //~| ERROR implementation of `Trait` is not general enough
} }

View file

@ -1,33 +1,3 @@
error: lifetime may not live long enough
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
|
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
| ^-^
| ||
| |has type `<&'1 () as Trait>::Ty`
| requires that `'1` must outlive `'static`
error: higher-ranked subtype error
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
|
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
| ^^^
error: higher-ranked subtype error
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
|
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
| ^^^
error: implementation of `Trait` is not general enough
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
|
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
| ^^^^^^ implementation of `Trait` is not general enough
|
= note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
= note: ...but `Trait` is actually implemented for the type `&'static ()`
error: implementation of `Trait` is not general enough error: implementation of `Trait` is not general enough
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:12 --> $DIR/closure-malformed-projection-input-issue-102800.rs:18:12
| |
@ -46,59 +16,5 @@ LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
= note: `&'0 ()` must implement `Trait`, for any lifetime `'0`... = note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
= note: ...but `Trait` is actually implemented for the type `&'static ()` = note: ...but `Trait` is actually implemented for the type `&'static ()`
error: implementation of `Trait` is not general enough error: aborting due to 2 previous errors
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:12
|
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Trait` is not general enough
|
= note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
= note: ...but `Trait` is actually implemented for the type `&'static ()`
error: implementation of `Trait` is not general enough
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:12
|
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Trait` is not general enough
|
= note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
= note: ...but `Trait` is actually implemented for the type `&'static ()`
error: implementation of `Trait` is not general enough
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
|
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
| ^^^^^^ implementation of `Trait` is not general enough
|
= note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
= note: ...but `Trait` is actually implemented for the type `&'static ()`
error: implementation of `Trait` is not general enough
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
|
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
| ^^^^^^ implementation of `Trait` is not general enough
|
= note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
= note: ...but `Trait` is actually implemented for the type `&'static ()`
error: implementation of `Trait` is not general enough
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
|
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
| ^^^^^^ implementation of `Trait` is not general enough
|
= note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
= note: ...but `Trait` is actually implemented for the type `&'static ()`
error: implementation of `Trait` is not general enough
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
|
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
| ^^^^^^ implementation of `Trait` is not general enough
|
= note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
= note: ...but `Trait` is actually implemented for the type `&'static ()`
error: aborting due to 12 previous errors

View file

@ -1,5 +1,5 @@
// check-pass // Regression test for #101350.
// known-bug: #101350 // check-fail
trait Trait { trait Trait {
type Ty; type Ty;
@ -11,6 +11,7 @@ impl Trait for &'static () {
fn extend<'a>() { fn extend<'a>() {
None::<<&'a () as Trait>::Ty>; None::<<&'a () as Trait>::Ty>;
//~^ ERROR lifetime may not live long enough
} }
fn main() {} fn main() {}

View file

@ -0,0 +1,10 @@
error: lifetime may not live long enough
--> $DIR/ascribed-type-wf.rs:13:5
|
LL | fn extend<'a>() {
| -- lifetime `'a` defined here
LL | None::<<&'a () as Trait>::Ty>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
error: aborting due to previous error

View file

@ -11,8 +11,10 @@ struct SomeStruct<T> { t: T }
#[rustc_dump_user_substs] #[rustc_dump_user_substs]
fn main() { fn main() {
SomeStruct { t: 22 }; // Nothing given, no annotation. SomeStruct { t: 22 }; // Nothing given, no annotation.
//~^ ERROR SomeStruct<^0>
SomeStruct::<_> { t: 22 }; // Nothing interesting given, no annotation. SomeStruct::<_> { t: 22 }; // Nothing interesting given, no annotation.
//~^ ERROR SomeStruct<^0>
SomeStruct::<u32> { t: 22 }; // No lifetime bounds given. SomeStruct::<u32> { t: 22 }; // No lifetime bounds given.

View file

@ -1,8 +1,20 @@
error: user substs: UserSubsts { substs: [&ReStatic u32], user_self_ty: None } error: user substs: UserSubsts { substs: [^0], user_self_ty: Some(UserSelfTy { impl_def_id: DefId(0:3 ~ dump_adt_brace_struct[4679]::SomeStruct), self_ty: SomeStruct<^0> }) }
--> $DIR/dump-adt-brace-struct.rs:19:5 --> $DIR/dump-adt-brace-struct.rs:13:5
|
LL | SomeStruct { t: 22 }; // Nothing given, no annotation.
| ^^^^^^^^^^^^^^^^^^^^
error: user substs: UserSubsts { substs: [^0], user_self_ty: Some(UserSelfTy { impl_def_id: DefId(0:3 ~ dump_adt_brace_struct[4679]::SomeStruct), self_ty: SomeStruct<^0> }) }
--> $DIR/dump-adt-brace-struct.rs:16:5
|
LL | SomeStruct::<_> { t: 22 }; // Nothing interesting given, no annotation.
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: user substs: UserSubsts { substs: [&ReStatic u32], user_self_ty: Some(UserSelfTy { impl_def_id: DefId(0:3 ~ dump_adt_brace_struct[4679]::SomeStruct), self_ty: SomeStruct<&ReStatic u32> }) }
--> $DIR/dump-adt-brace-struct.rs:21:5
| |
LL | SomeStruct::<&'static u32> { t: &22 }; LL | SomeStruct::<&'static u32> { t: &22 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error error: aborting due to 3 previous errors

View file

@ -0,0 +1,80 @@
// Make sure we honor region constraints when normalizing type annotations.
// check-fail
#![feature(more_qualified_paths)]
trait Trait {
type Assoc;
}
impl<T> Trait for T
where
T: 'static,
{
type Assoc = MyTy<()>;
}
enum MyTy<T> {
Unit,
Tuple(),
Struct {},
Dumb(T),
}
impl<T> MyTy<T> {
fn method<X>() {}
}
type Ty<'a> = <&'a () as Trait>::Assoc;
fn test_local<'a>() {
let _: Ty<'a> = MyTy::Unit;
//~^ ERROR lifetime may not live long enough
}
fn test_closure_sig<'a, 'b>() {
|_: Ty<'a>| {};
//~^ ERROR lifetime may not live long enough
|| -> Option<Ty<'b>> { None };
//~^ ERROR lifetime may not live long enough
}
fn test_path<'a, 'b, 'c, 'd>() {
<Ty<'a>>::method::<Ty<'static>>;
//~^ ERROR lifetime may not live long enough
<Ty<'static>>::method::<Ty<'b>>;
//~^ ERROR lifetime may not live long enough
}
fn test_call<'a, 'b, 'c>() {
<Ty<'a>>::method::<Ty<'static>>();
//~^ ERROR lifetime may not live long enough
<Ty<'static>>::method::<Ty<'b>>();
//~^ ERROR lifetime may not live long enough
}
fn test_variants<'a, 'b, 'c>() {
<Ty<'a>>::Struct {}; //TODO
//~^ ERROR lifetime may not live long enough
<Ty<'b>>::Tuple();
//~^ ERROR lifetime may not live long enough
<Ty<'c>>::Unit;
//~^ ERROR lifetime may not live long enough
}
fn test_pattern<'a, 'b, 'c>() {
use MyTy::*;
match MyTy::Unit {
Struct::<Ty<'a>> {..} => {},
//~^ ERROR lifetime may not live long enough
Tuple::<Ty<'b>> (..) => {},
//~^ ERROR lifetime may not live long enough
Unit::<Ty<'c>> => {},
//~^ ERROR lifetime may not live long enough
Dumb(_) => {},
};
}
fn main() {}

View file

@ -0,0 +1,141 @@
error: lifetime may not live long enough
--> $DIR/normalization-2.rs:32:12
|
LL | fn test_local<'a>() {
| -- lifetime `'a` defined here
LL | let _: Ty<'a> = MyTy::Unit;
| ^^^^^^ requires that `'a` must outlive `'static`
error: lifetime may not live long enough
--> $DIR/normalization-2.rs:37:6
|
LL | fn test_closure_sig<'a, 'b>() {
| -- lifetime `'a` defined here
LL | |_: Ty<'a>| {};
| ^ requires that `'a` must outlive `'static`
error: lifetime may not live long enough
--> $DIR/normalization-2.rs:39:11
|
LL | fn test_closure_sig<'a, 'b>() {
| -- lifetime `'b` defined here
...
LL | || -> Option<Ty<'b>> { None };
| ^^^^^^^^^^^^^^ requires that `'b` must outlive `'static`
help: the following changes may resolve your lifetime errors
|
= help: replace `'a` with `'static`
= help: replace `'b` with `'static`
error: lifetime may not live long enough
--> $DIR/normalization-2.rs:44:5
|
LL | fn test_path<'a, 'b, 'c, 'd>() {
| -- lifetime `'a` defined here
LL | <Ty<'a>>::method::<Ty<'static>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
error: lifetime may not live long enough
--> $DIR/normalization-2.rs:46:5
|
LL | fn test_path<'a, 'b, 'c, 'd>() {
| -- lifetime `'b` defined here
...
LL | <Ty<'static>>::method::<Ty<'b>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static`
help: the following changes may resolve your lifetime errors
|
= help: replace `'a` with `'static`
= help: replace `'b` with `'static`
error: lifetime may not live long enough
--> $DIR/normalization-2.rs:51:5
|
LL | fn test_call<'a, 'b, 'c>() {
| -- lifetime `'a` defined here
LL | <Ty<'a>>::method::<Ty<'static>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
error: lifetime may not live long enough
--> $DIR/normalization-2.rs:53:5
|
LL | fn test_call<'a, 'b, 'c>() {
| -- lifetime `'b` defined here
...
LL | <Ty<'static>>::method::<Ty<'b>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static`
help: the following changes may resolve your lifetime errors
|
= help: replace `'a` with `'static`
= help: replace `'b` with `'static`
error: lifetime may not live long enough
--> $DIR/normalization-2.rs:58:5
|
LL | fn test_variants<'a, 'b, 'c>() {
| -- lifetime `'a` defined here
LL | <Ty<'a>>::Struct {}; //TODO
| ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
error: lifetime may not live long enough
--> $DIR/normalization-2.rs:60:5
|
LL | fn test_variants<'a, 'b, 'c>() {
| -- lifetime `'b` defined here
...
LL | <Ty<'b>>::Tuple();
| ^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static`
error: lifetime may not live long enough
--> $DIR/normalization-2.rs:62:5
|
LL | fn test_variants<'a, 'b, 'c>() {
| -- lifetime `'c` defined here
...
LL | <Ty<'c>>::Unit;
| ^^^^^^^^^^^^^^ requires that `'c` must outlive `'static`
help: the following changes may resolve your lifetime errors
|
= help: replace `'a` with `'static`
= help: replace `'b` with `'static`
= help: replace `'c` with `'static`
error: lifetime may not live long enough
--> $DIR/normalization-2.rs:69:9
|
LL | fn test_pattern<'a, 'b, 'c>() {
| -- lifetime `'a` defined here
...
LL | Struct::<Ty<'a>> {..} => {},
| ^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
error: lifetime may not live long enough
--> $DIR/normalization-2.rs:71:9
|
LL | fn test_pattern<'a, 'b, 'c>() {
| -- lifetime `'b` defined here
...
LL | Tuple::<Ty<'b>> (..) => {},
| ^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static`
error: lifetime may not live long enough
--> $DIR/normalization-2.rs:73:9
|
LL | fn test_pattern<'a, 'b, 'c>() {
| -- lifetime `'c` defined here
...
LL | Unit::<Ty<'c>> => {},
| ^^^^^^^^^^^^^^ requires that `'c` must outlive `'static`
help: the following changes may resolve your lifetime errors
|
= help: replace `'a` with `'static`
= help: replace `'b` with `'static`
= help: replace `'c` with `'static`
error: aborting due to 13 previous errors

View file

@ -205,7 +205,7 @@ error[E0223]: ambiguous associated type
--> $DIR/ufcs-partially-resolved.rs:36:12 --> $DIR/ufcs-partially-resolved.rs:36:12
| |
LL | let _: <u8 as Tr>::Y::NN; LL | let _: <u8 as Tr>::Y::NN;
| ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<u16 as Trait>::NN` | ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<<u8 as Tr>::Y as Trait>::NN`
error[E0599]: no associated item named `NN` found for type `u16` in the current scope error[E0599]: no associated item named `NN` found for type `u16` in the current scope
--> $DIR/ufcs-partially-resolved.rs:38:20 --> $DIR/ufcs-partially-resolved.rs:38:20