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>,
) -> Ty<'tcx>;
/// Normalize an associated type coming from the user.
///
/// 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>;
fn normalize_ty_2(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
ty
}
/// Invoked when we encounter an error from some prior pass
/// (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.
return tcx.ty_error().into();
}
self.astconv
.normalize_ty(
self.span,
tcx.at(self.span)
.bound_type_of(param.def_id)
.subst(tcx, substs),
)
.into()
tcx.at(self.span).bound_type_of(param.def_id).subst(tcx, substs).into()
} else if infer_args {
self.astconv.ty_infer(Some(param), self.span).into()
} else {
@ -1254,7 +1245,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
item_segment: &hir::PathSegment<'_>,
) -> Ty<'tcx> {
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(
@ -1786,7 +1777,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
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`
// and item_segment is the path segment for `D`. We return a type and a def for
// the whole path.
@ -1814,7 +1805,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// Check if we have an enum variant.
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() {
let variant_def = adt_def
.variants()
@ -1923,7 +1914,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
adt_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));
}
}
@ -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.normalize_ty(span, ty);
if let Some(variant_def_id) = variant_resolution {
tcx.struct_span_lint_hir(
@ -2156,7 +2145,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
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>(
@ -2417,7 +2406,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
err.note("`impl Trait` types can't have type parameters");
});
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(
DefKind::Enum
@ -2577,7 +2566,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
tcx.ty_error_with_guaranteed(err.emit())
} else {
self.normalize_ty(span, ty)
ty
}
}
Res::Def(DefKind::AssocTy, def_id) => {
@ -2720,8 +2709,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
None,
ty::BoundConstness::NotConst,
);
EarlyBinder(self.normalize_ty(span, tcx.at(span).type_of(def_id)))
.subst(tcx, substs)
EarlyBinder(tcx.at(span).type_of(def_id)).subst(tcx, substs)
}
hir::TyKind::Array(ref ty, ref 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));
self.normalize_ty(ast_ty.span, array_ty)
tcx.mk_ty(ty::Array(self.ast_ty_to_ty(ty), length))
}
hir::TyKind::Typeof(ref e) => {
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) {
// 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,
);
// 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);
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

View File

@ -1,7 +1,7 @@
use crate::callee::{self, DeferredCallResolution};
use crate::method::{self, MethodCallee, SelfSource};
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::fx::FxHashSet;
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);
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> {
let ty = self.to_ty(ast_ty);
debug!("to_ty_saving_user_provided_ty: ty={:?}", ty);
if Self::can_contain_user_lifetime_bounds(ty) {
let c_ty = self.canonicalize_response(UserType::Ty(ty));
if Self::can_contain_user_lifetime_bounds(ty.raw) {
let c_ty = self.canonicalize_response(UserType::Ty(ty.raw));
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);
}
ty
ty.normalized
}
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>,
hir_id: hir::HirId,
span: Span,
) -> (Res, Option<Ty<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) {
) -> (Res, Option<RawTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) {
debug!(
"resolve_ty_and_res_fully_qualified_call: qpath={:?} hir_id={:?} span={:?}",
qpath, hir_id, span
@ -803,7 +807,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// to be object-safe.
// We manually call `register_wf_obligation` in the success path
// 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(..) => {
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)
{
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
// errors with default match binding modes. See #44614.
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 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| {
let result = match error {
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,
// register a WF obligation so that we can detect any additional
// errors in the self type.
if !(matches!(error, method::MethodError::NoMatch(_)) && ty.is_trait()) {
self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None));
if !(matches!(error, method::MethodError::NoMatch(_)) && ty.normalized.is_trait()) {
self.register_wf_obligation(
ty.raw.into(),
qself.span,
traits::WellFormed(None),
);
}
if item_name.name != kw::Empty {
if let Some(mut e) = self.report_method_error(
span,
ty,
ty.normalized,
item_name,
SelfSource::QPath(qself),
error,
@ -849,7 +858,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
});
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.
@ -986,7 +995,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn instantiate_value_path(
&self,
segments: &[hir::PathSegment<'_>],
self_ty: Option<Ty<'tcx>>,
self_ty: Option<RawTy<'tcx>>,
res: Res,
span: Span,
hir_id: hir::HirId,
@ -996,7 +1005,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let path_segs = match res {
Res::Local(_) | Res::SelfCtor(_) => vec![],
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),
};
@ -1007,8 +1020,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Res::Def(DefKind::Ctor(CtorOf::Variant, _), _)
if let Some(self_ty) = self_ty =>
{
let adt_def = self_ty.ty_adt_def().unwrap();
user_self_ty = Some(UserSelfTy { impl_def_id: adt_def.did(), self_ty });
let adt_def = self_ty.normalized.ty_adt_def().unwrap();
user_self_ty = Some(UserSelfTy { impl_def_id: adt_def.did(), self_ty: self_ty.raw });
is_alias_variant_ctor = true;
}
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
// `T` for posterity (see `UserSelfTy` for
// 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 });
}
}
@ -1109,7 +1122,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.unwrap_or(false);
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() {
ty::Adt(adt_def, substs) if adt_def.has_ctor() => {
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()
}
(GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
self.fcx.to_ty(ty).into()
self.fcx.to_ty(ty).raw.into()
}
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
self.fcx.const_arg_to_const(&ct.value, param.def_id).into()
@ -1227,7 +1240,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// is missing.
let default = tcx.bound_type_of(param.def_id);
self.fcx
.normalize_ty(self.span, default.subst(tcx, substs.unwrap()))
.normalize_ty_2(self.span, default.subst(tcx, substs.unwrap()))
.into()
} else {
// 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(
tcx,
def_id,
&[],
has_self,
self_ty,
self_ty.map(|s| s.raw),
&arg_count,
&mut CreateCtorSubstsContext {
fcx: self,
@ -1269,7 +1282,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
});
// 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);
@ -1287,6 +1303,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// with the substituted impl type.
// 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 self_ty = self.normalize(span, self_ty);
match self.at(&self.misc(span), self.param_env).eq(impl_ty, self_ty) {
Ok(ok) => self.register_infer_ok_obligations(ok),
Err(_) => {

View File

@ -5,7 +5,7 @@ use crate::method::MethodCallee;
use crate::Expectation::*;
use crate::TupleArgumentsFlag::*;
use crate::{
struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy, Needs,
struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy, Needs, RawTy,
TupleArgumentsFlag,
};
use rustc_ast as ast;
@ -1231,13 +1231,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
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)),
_ => bug!("unexpected type: {:?}", ty),
_ => bug!("unexpected type: {:?}", ty.normalized),
},
Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _)
| Res::SelfTyParam { .. }
| Res::SelfTyAlias { .. } => match ty.kind() {
| Res::SelfTyAlias { .. } => match ty.normalized.kind() {
ty::Adt(adt, substs) if !adt.is_enum() => {
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 {
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.
self.add_required_obligations_for_hir(path_span, did, substs, hir_id);
Some((variant, ty))
Some((variant, ty.normalized))
} else {
match ty.kind() {
match ty.normalized.kind() {
ty::Error(_) => {
// E0071 might be caused by a spelling error, which will have
// already caused an error message and probably a suggestion
@ -1268,7 +1272,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
path_span,
E0071,
"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")
.emit();
@ -1656,20 +1660,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
qpath: &QPath<'_>,
path_span: Span,
hir_id: hir::HirId,
) -> (Res, Ty<'tcx>) {
) -> (Res, RawTy<'tcx>) {
match *qpath {
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);
(path.res, ty)
(path.res, self.create_raw_ty(path_span, ty))
}
QPath::TypeRelative(ref qself, ref segment) => {
let ty = self.to_ty(qself);
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 = self.create_raw_ty(path_span, ty);
let result = result.map(|(_, kind, def_id)| (kind, def_id));
// 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)
}
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_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::visit::TypeVisitable;
use rustc_middle::ty::{self, Const, Ty, TyCtxt};
use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitable};
use rustc_session::Session;
use rustc_span::symbol::Ident;
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)
}
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() {
ty // FIXME: normalization and escaping regions
} else {
@ -310,7 +309,19 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
self.infcx.set_tainted_by_errors(e)
}
fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, _span: Span) {
self.write_ty(hir_id, ty)
fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span) {
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) => {
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);
self.fcx
.typeck_results
@ -85,7 +86,7 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
.user_provided_types_mut()
.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,
};

View File

@ -297,7 +297,7 @@ fn typeck_with_fallback<'tcx>(
fcx.resolve_generator_interiors(def_id.to_def_id());
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);
}

View File

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

View File

@ -1,4 +1,4 @@
use crate::FnCtxt;
use crate::{FnCtxt, RawTy};
use rustc_ast as ast;
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{
@ -842,7 +842,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
pat: &Pat<'tcx>,
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>,
ti: TopInfo<'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 {
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 = 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)]
#![allow(incomplete_features)]

View File

@ -14,14 +14,6 @@ fn foo<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` 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
// 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) = |_, _| ();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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: aborting due to 2 previous errors
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>() {
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]
}
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
--> $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>>() {
| +++++++++++++++++++++++
error: aborting due to previous error
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@ -16,16 +16,6 @@ impl Trait for &'static () {
fn main() {
let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
//~^ ERROR lifetime may not live long 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
--> $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: ...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: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
error: aborting due to 2 previous errors

View File

@ -1,5 +1,5 @@
// check-pass
// known-bug: #101350
// Regression test for #101350.
// check-fail
trait Trait {
type Ty;
@ -11,6 +11,7 @@ impl Trait for &'static () {
fn extend<'a>() {
None::<<&'a () as Trait>::Ty>;
//~^ ERROR lifetime may not live long enough
}
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]
fn main() {
SomeStruct { t: 22 }; // Nothing given, no annotation.
//~^ ERROR SomeStruct<^0>
SomeStruct::<_> { t: 22 }; // Nothing interesting given, no annotation.
//~^ ERROR SomeStruct<^0>
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 }
--> $DIR/dump-adt-brace-struct.rs:19:5
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: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 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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
|
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
--> $DIR/ufcs-partially-resolved.rs:38:20