add TypingMode::Borrowck

This commit is contained in:
lcnr 2025-04-01 23:48:41 +02:00
parent 990201cb78
commit 509a144eed
131 changed files with 888 additions and 747 deletions

View file

@ -35,7 +35,7 @@ use rustc_infer::infer::{
}; };
use rustc_middle::mir::*; use rustc_middle::mir::*;
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt, TypingMode, fold_regions}; use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt, TypingMode};
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_mir_dataflow::impls::{ use rustc_mir_dataflow::impls::{
EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces, EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces,
@ -171,12 +171,6 @@ fn do_mir_borrowck<'tcx>(
let free_regions = nll::replace_regions_in_mir(&infcx, &mut body_owned, &mut promoted); let free_regions = nll::replace_regions_in_mir(&infcx, &mut body_owned, &mut promoted);
let body = &body_owned; // no further changes let body = &body_owned; // no further changes
// FIXME(-Znext-solver): A bit dubious that we're only registering
// predefined opaques in the typeck root.
if infcx.next_trait_solver() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
infcx.register_predefined_opaques_for_next_solver(def);
}
let location_table = PoloniusLocationTable::new(body); let location_table = PoloniusLocationTable::new(body);
let move_data = MoveData::gather_moves(body, tcx, |_| true); let move_data = MoveData::gather_moves(body, tcx, |_| true);
@ -431,7 +425,12 @@ pub(crate) struct BorrowckInferCtxt<'tcx> {
impl<'tcx> BorrowckInferCtxt<'tcx> { impl<'tcx> BorrowckInferCtxt<'tcx> {
pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, def_id)); let typing_mode = if tcx.use_typing_mode_borrowck() {
TypingMode::borrowck(tcx, def_id)
} else {
TypingMode::analysis_in_body(tcx, def_id)
};
let infcx = tcx.infer_ctxt().build(typing_mode);
let param_env = tcx.param_env(def_id); let param_env = tcx.param_env(def_id);
BorrowckInferCtxt { infcx, reg_var_to_origin: RefCell::new(Default::default()), param_env } BorrowckInferCtxt { infcx, reg_var_to_origin: RefCell::new(Default::default()), param_env }
} }
@ -478,29 +477,6 @@ impl<'tcx> BorrowckInferCtxt<'tcx> {
next_region next_region
} }
/// With the new solver we prepopulate the opaque type storage during
/// MIR borrowck with the hidden types from HIR typeck. This is necessary
/// to avoid ambiguities as earlier goals can rely on the hidden type
/// of an opaque which is only constrained by a later goal.
fn register_predefined_opaques_for_next_solver(&self, def_id: LocalDefId) {
let tcx = self.tcx;
// OK to use the identity arguments for each opaque type key, since
// we remap opaques from HIR typeck back to their definition params.
for data in tcx.typeck(def_id).concrete_opaque_types.iter().map(|(k, v)| (*k, *v)) {
// HIR typeck did not infer the regions of the opaque, so we instantiate
// them with fresh inference variables.
let (key, hidden_ty) = fold_regions(tcx, data, |_, _| {
self.next_nll_region_var_in_universe(
NllRegionVariableOrigin::Existential { from_forall: false },
ty::UniverseIndex::ROOT,
)
});
let prev = self.register_hidden_type_in_storage(key, hidden_ty);
assert_eq!(prev, None);
}
}
} }
impl<'tcx> Deref for BorrowckInferCtxt<'tcx> { impl<'tcx> Deref for BorrowckInferCtxt<'tcx> {

View file

@ -2,7 +2,8 @@ use rustc_data_structures::fx::FxIndexMap;
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin}; use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
use rustc_macros::extension; use rustc_macros::extension;
use rustc_middle::ty::{ use rustc_middle::ty::{
self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, fold_regions, self, DefiningScopeKind, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable,
TypeVisitableExt, fold_regions,
}; };
use rustc_span::Span; use rustc_span::Span;
use rustc_trait_selection::opaque_types::check_opaque_type_parameter_valid; use rustc_trait_selection::opaque_types::check_opaque_type_parameter_valid;
@ -266,14 +267,21 @@ impl<'tcx> InferCtxt<'tcx> {
return Ty::new_error(self.tcx, e); return Ty::new_error(self.tcx, e);
} }
if let Err(guar) = if let Err(guar) = check_opaque_type_parameter_valid(
check_opaque_type_parameter_valid(self, opaque_type_key, instantiated_ty.span) self,
{ opaque_type_key,
instantiated_ty.span,
DefiningScopeKind::MirBorrowck,
) {
return Ty::new_error(self.tcx, guar); return Ty::new_error(self.tcx, guar);
} }
let definition_ty = instantiated_ty let definition_ty = instantiated_ty
.remap_generic_params_to_declaration_params(opaque_type_key, self.tcx, false) .remap_generic_params_to_declaration_params(
opaque_type_key,
self.tcx,
DefiningScopeKind::MirBorrowck,
)
.ty; .ty;
if let Err(e) = definition_ty.error_reported() { if let Err(e) = definition_ty.error_reported() {

View file

@ -61,6 +61,7 @@ pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers { *providers = Providers {
type_of: type_of::type_of, type_of: type_of::type_of,
type_of_opaque: type_of::type_of_opaque, type_of_opaque: type_of::type_of_opaque,
type_of_opaque_hir_typeck: type_of::type_of_opaque_hir_typeck,
type_alias_is_lazy: type_of::type_alias_is_lazy, type_alias_is_lazy: type_of::type_alias_is_lazy,
item_bounds: item_bounds::item_bounds, item_bounds: item_bounds::item_bounds,
explicit_item_bounds: item_bounds::explicit_item_bounds, explicit_item_bounds: item_bounds::explicit_item_bounds,

View file

@ -7,7 +7,9 @@ use rustc_hir::{self as hir, AmbigArg, HirId};
use rustc_middle::query::plumbing::CyclePlaceholder; use rustc_middle::query::plumbing::CyclePlaceholder;
use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, fold_regions}; use rustc_middle::ty::{
self, DefiningScopeKind, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, fold_regions,
};
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_span::{DUMMY_SP, Ident, Span}; use rustc_span::{DUMMY_SP, Ident, Span};
@ -324,10 +326,18 @@ pub(super) fn type_of_opaque(
if let Some(def_id) = def_id.as_local() { if let Some(def_id) = def_id.as_local() {
Ok(ty::EarlyBinder::bind(match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin { Ok(ty::EarlyBinder::bind(match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin {
hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. } => { hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. } => {
opaque::find_opaque_ty_constraints_for_tait(tcx, def_id) opaque::find_opaque_ty_constraints_for_tait(
tcx,
def_id,
DefiningScopeKind::MirBorrowck,
)
} }
hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: true, .. } => { hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: true, .. } => {
opaque::find_opaque_ty_constraints_for_impl_trait_in_assoc_type(tcx, def_id) opaque::find_opaque_ty_constraints_for_impl_trait_in_assoc_type(
tcx,
def_id,
DefiningScopeKind::MirBorrowck,
)
} }
// Opaque types desugared from `impl Trait`. // Opaque types desugared from `impl Trait`.
hir::OpaqueTyOrigin::FnReturn { parent: owner, in_trait_or_impl } hir::OpaqueTyOrigin::FnReturn { parent: owner, in_trait_or_impl }
@ -340,7 +350,12 @@ pub(super) fn type_of_opaque(
"tried to get type of this RPITIT with no definition" "tried to get type of this RPITIT with no definition"
); );
} }
opaque::find_opaque_ty_constraints_for_rpit(tcx, def_id, owner) opaque::find_opaque_ty_constraints_for_rpit(
tcx,
def_id,
owner,
DefiningScopeKind::MirBorrowck,
)
} }
})) }))
} else { } else {
@ -350,6 +365,42 @@ pub(super) fn type_of_opaque(
} }
} }
pub(super) fn type_of_opaque_hir_typeck(
tcx: TyCtxt<'_>,
def_id: LocalDefId,
) -> ty::EarlyBinder<'_, Ty<'_>> {
ty::EarlyBinder::bind(match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin {
hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. } => {
opaque::find_opaque_ty_constraints_for_tait(tcx, def_id, DefiningScopeKind::HirTypeck)
}
hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: true, .. } => {
opaque::find_opaque_ty_constraints_for_impl_trait_in_assoc_type(
tcx,
def_id,
DefiningScopeKind::HirTypeck,
)
}
// Opaque types desugared from `impl Trait`.
hir::OpaqueTyOrigin::FnReturn { parent: owner, in_trait_or_impl }
| hir::OpaqueTyOrigin::AsyncFn { parent: owner, in_trait_or_impl } => {
if in_trait_or_impl == Some(hir::RpitContext::Trait)
&& !tcx.defaultness(owner).has_value()
{
span_bug!(
tcx.def_span(def_id),
"tried to get type of this RPITIT with no definition"
);
}
opaque::find_opaque_ty_constraints_for_rpit(
tcx,
def_id,
owner,
DefiningScopeKind::HirTypeck,
)
}
})
}
fn infer_placeholder_type<'tcx>( fn infer_placeholder_type<'tcx>(
cx: &dyn HirTyLowerer<'tcx>, cx: &dyn HirTyLowerer<'tcx>,
def_id: LocalDefId, def_id: LocalDefId,

View file

@ -3,8 +3,7 @@ use rustc_hir::def_id::LocalDefId;
use rustc_hir::{self as hir, Expr, ImplItem, Item, Node, TraitItem, def, intravisit}; use rustc_hir::{self as hir, Expr, ImplItem, Item, Node, TraitItem, def, intravisit};
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::hir::nested_filter; use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{self, DefiningScopeKind, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::DUMMY_SP;
use tracing::{debug, instrument, trace}; use tracing::{debug, instrument, trace};
use crate::errors::{TaitForwardCompat2, UnconstrainedOpaqueType}; use crate::errors::{TaitForwardCompat2, UnconstrainedOpaqueType};
@ -15,6 +14,7 @@ use crate::errors::{TaitForwardCompat2, UnconstrainedOpaqueType};
pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type( pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
def_id: LocalDefId, def_id: LocalDefId,
opaque_types_from: DefiningScopeKind,
) -> Ty<'_> { ) -> Ty<'_> {
let mut parent_def_id = def_id; let mut parent_def_id = def_id;
while tcx.def_kind(parent_def_id) == def::DefKind::OpaqueTy { while tcx.def_kind(parent_def_id) == def::DefKind::OpaqueTy {
@ -27,7 +27,7 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type(
other => bug!("invalid impl trait in assoc type parent: {other:?}"), other => bug!("invalid impl trait in assoc type parent: {other:?}"),
} }
let mut locator = TaitConstraintLocator { def_id, tcx, found: None, typeck_types: vec![] }; let mut locator = TaitConstraintLocator { def_id, tcx, found: None, opaque_types_from };
for &assoc_id in tcx.associated_item_def_ids(impl_def_id) { for &assoc_id in tcx.associated_item_def_ids(impl_def_id) {
let assoc = tcx.associated_item(assoc_id); let assoc = tcx.associated_item(assoc_id);
@ -39,25 +39,14 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type(
} }
if let Some(hidden) = locator.found { if let Some(hidden) = locator.found {
// Only check against typeck if we didn't already error
if !hidden.ty.references_error() {
for concrete_type in locator.typeck_types {
if concrete_type.ty != tcx.erase_regions(hidden.ty) {
if let Ok(d) = hidden.build_mismatch_error(&concrete_type, tcx) {
d.emit();
}
}
}
}
hidden.ty hidden.ty
} else { } else {
let reported = tcx.dcx().emit_err(UnconstrainedOpaqueType { let guar = tcx.dcx().emit_err(UnconstrainedOpaqueType {
span: tcx.def_span(def_id), span: tcx.def_span(def_id),
name: tcx.item_ident(parent_def_id.to_def_id()), name: tcx.item_ident(parent_def_id.to_def_id()),
what: "impl", what: "impl",
}); });
Ty::new_error(tcx, reported) Ty::new_error(tcx, guar)
} }
} }
@ -80,23 +69,16 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type(
/// fn b<T>() -> Foo<T, u32> { .. } /// fn b<T>() -> Foo<T, u32> { .. }
/// ``` /// ```
#[instrument(skip(tcx), level = "debug")] #[instrument(skip(tcx), level = "debug")]
pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { pub(super) fn find_opaque_ty_constraints_for_tait(
let mut locator = TaitConstraintLocator { def_id, tcx, found: None, typeck_types: vec![] }; tcx: TyCtxt<'_>,
def_id: LocalDefId,
opaque_types_from: DefiningScopeKind,
) -> Ty<'_> {
let mut locator = TaitConstraintLocator { def_id, tcx, found: None, opaque_types_from };
tcx.hir_walk_toplevel_module(&mut locator); tcx.hir_walk_toplevel_module(&mut locator);
if let Some(hidden) = locator.found { if let Some(hidden) = locator.found {
// Only check against typeck if we didn't already error
if !hidden.ty.references_error() {
for concrete_type in locator.typeck_types {
if concrete_type.ty != tcx.erase_regions(hidden.ty) {
if let Ok(d) = hidden.build_mismatch_error(&concrete_type, tcx) {
d.emit();
}
}
}
}
hidden.ty hidden.ty
} else { } else {
let mut parent_def_id = def_id; let mut parent_def_id = def_id;
@ -104,12 +86,12 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
// Account for `type Alias = impl Trait<Foo = impl Trait>;` (#116031) // Account for `type Alias = impl Trait<Foo = impl Trait>;` (#116031)
parent_def_id = tcx.local_parent(parent_def_id); parent_def_id = tcx.local_parent(parent_def_id);
} }
let reported = tcx.dcx().emit_err(UnconstrainedOpaqueType { let guar = tcx.dcx().emit_err(UnconstrainedOpaqueType {
span: tcx.def_span(def_id), span: tcx.def_span(def_id),
name: tcx.item_ident(parent_def_id.to_def_id()), name: tcx.item_ident(parent_def_id.to_def_id()),
what: "crate", what: "crate",
}); });
Ty::new_error(tcx, reported) Ty::new_error(tcx, guar)
} }
} }
@ -126,22 +108,44 @@ struct TaitConstraintLocator<'tcx> {
/// type). /// type).
found: Option<ty::OpaqueHiddenType<'tcx>>, found: Option<ty::OpaqueHiddenType<'tcx>>,
/// In the presence of dead code, typeck may figure out a hidden type opaque_types_from: DefiningScopeKind,
/// while borrowck will not. We collect these cases here and check at
/// the end that we actually found a type that matches (modulo regions).
typeck_types: Vec<ty::OpaqueHiddenType<'tcx>>,
} }
impl TaitConstraintLocator<'_> { impl<'tcx> TaitConstraintLocator<'tcx> {
fn insert_found(&mut self, hidden_ty: ty::OpaqueHiddenType<'tcx>) {
if let Some(prev) = &mut self.found {
if hidden_ty.ty != prev.ty {
let (Ok(guar) | Err(guar)) =
prev.build_mismatch_error(&hidden_ty, self.tcx).map(|d| d.emit());
prev.ty = Ty::new_error(self.tcx, guar);
}
} else {
self.found = Some(hidden_ty);
}
}
fn non_defining_use_in_defining_scope(&mut self, item_def_id: LocalDefId) {
let guar = self.tcx.dcx().emit_err(TaitForwardCompat2 {
span: self
.tcx
.def_ident_span(item_def_id)
.unwrap_or_else(|| self.tcx.def_span(item_def_id)),
opaque_type_span: self.tcx.def_span(self.def_id),
opaque_type: self.tcx.def_path_str(self.def_id),
});
self.insert_found(ty::OpaqueHiddenType::new_error(self.tcx, guar));
}
#[instrument(skip(self), level = "debug")] #[instrument(skip(self), level = "debug")]
fn check(&mut self, item_def_id: LocalDefId) { fn check(&mut self, item_def_id: LocalDefId) {
// Don't try to check items that cannot possibly constrain the type. // Don't try to check items that cannot possibly constrain the type.
if !self.tcx.has_typeck_results(item_def_id) { let tcx = self.tcx;
if !tcx.has_typeck_results(item_def_id) {
debug!("no constraint: no typeck results"); debug!("no constraint: no typeck results");
return; return;
} }
let opaque_types_defined_by = self.tcx.opaque_types_defined_by(item_def_id); let opaque_types_defined_by = tcx.opaque_types_defined_by(item_def_id);
// Don't try to check items that cannot possibly constrain the type. // Don't try to check items that cannot possibly constrain the type.
if !opaque_types_defined_by.contains(&self.def_id) { if !opaque_types_defined_by.contains(&self.def_id) {
debug!("no constraint: no opaque types defined"); debug!("no constraint: no opaque types defined");
@ -152,7 +156,7 @@ impl TaitConstraintLocator<'_> {
// "non-defining use" errors for them. // "non-defining use" errors for them.
// Note that we use `Node::fn_sig` instead of `Node::fn_decl` here, because the former // Note that we use `Node::fn_sig` instead of `Node::fn_decl` here, because the former
// excludes closures, which are allowed to have `_` in their return type. // excludes closures, which are allowed to have `_` in their return type.
let hir_node = self.tcx.hir_node_by_def_id(item_def_id); let hir_node = tcx.hir_node_by_def_id(item_def_id);
debug_assert!( debug_assert!(
!matches!(hir_node, Node::ForeignItem(..)), !matches!(hir_node, Node::ForeignItem(..)),
"foreign items cannot constrain opaque types", "foreign items cannot constrain opaque types",
@ -164,88 +168,39 @@ impl TaitConstraintLocator<'_> {
hir_sig.decl.output.span(), hir_sig.decl.output.span(),
"inferring return types and opaque types do not mix well", "inferring return types and opaque types do not mix well",
); );
self.found = self.found = Some(ty::OpaqueHiddenType::new_error(tcx, guar));
Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: Ty::new_error(self.tcx, guar) });
return; return;
} }
// Calling `mir_borrowck` can lead to cycle errors through match self.opaque_types_from {
// const-checking, avoid calling it if we don't have to. DefiningScopeKind::HirTypeck => {
// ```rust let tables = tcx.typeck(item_def_id);
// type Foo = impl Fn() -> usize; // when computing type for this if let Some(guar) = tables.tainted_by_errors {
// const fn bar() -> Foo { self.insert_found(ty::OpaqueHiddenType::new_error(tcx, guar));
// || 0usize } else if let Some(&hidden_type) = tables.concrete_opaque_types.get(&self.def_id) {
// } self.insert_found(hidden_type);
// const BAZR: Foo = bar(); // we would mir-borrowck this, causing cycles } else {
// // because we again need to reveal `Foo` so we can check whether the self.non_defining_use_in_defining_scope(item_def_id);
// // constant does not contain interior mutability. }
// ``` }
let tables = self.tcx.typeck(item_def_id); DefiningScopeKind::MirBorrowck => {
if let Some(guar) = tables.tainted_by_errors { let borrowck_result = tcx.mir_borrowck(item_def_id);
self.found = if let Some(guar) = borrowck_result.tainted_by_errors {
Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: Ty::new_error(self.tcx, guar) }); self.insert_found(ty::OpaqueHiddenType::new_error(tcx, guar));
return; } else if let Some(&hidden_type) =
} borrowck_result.concrete_opaque_types.get(&self.def_id)
{
let mut constrained = false; debug!(?hidden_type, "found constraint");
for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types { self.insert_found(hidden_type);
if opaque_type_key.def_id != self.def_id { } else if let Err(guar) = tcx
continue; .type_of_opaque_hir_typeck(self.def_id)
} .instantiate_identity()
constrained = true; .error_reported()
{
let concrete_type = self.insert_found(ty::OpaqueHiddenType::new_error(tcx, guar));
self.tcx.erase_regions(hidden_type.remap_generic_params_to_declaration_params( } else {
opaque_type_key, self.non_defining_use_in_defining_scope(item_def_id);
self.tcx,
true,
));
if self.typeck_types.iter().all(|prev| prev.ty != concrete_type.ty) {
self.typeck_types.push(concrete_type);
}
}
if !constrained {
debug!("no constraints in typeck results");
if opaque_types_defined_by.contains(&self.def_id) {
let guar = self.tcx.dcx().emit_err(TaitForwardCompat2 {
span: self
.tcx
.def_ident_span(item_def_id)
.unwrap_or_else(|| self.tcx.def_span(item_def_id)),
opaque_type_span: self.tcx.def_span(self.def_id),
opaque_type: self.tcx.def_path_str(self.def_id),
});
// Avoid "opaque type not constrained" errors on the opaque itself.
self.found = Some(ty::OpaqueHiddenType {
span: DUMMY_SP,
ty: Ty::new_error(self.tcx, guar),
});
}
return;
};
// Use borrowck to get the type with unerased regions.
let borrowck_results = &self.tcx.mir_borrowck(item_def_id);
// If the body was tainted, then assume the opaque may have been constrained and just set it to error.
if let Some(guar) = borrowck_results.tainted_by_errors {
self.found =
Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: Ty::new_error(self.tcx, guar) });
return;
}
debug!(?borrowck_results.concrete_opaque_types);
if let Some(&concrete_type) = borrowck_results.concrete_opaque_types.get(&self.def_id) {
debug!(?concrete_type, "found constraint");
if let Some(prev) = &mut self.found {
if concrete_type.ty != prev.ty {
let (Ok(guar) | Err(guar)) =
prev.build_mismatch_error(&concrete_type, self.tcx).map(|d| d.emit());
prev.ty = Ty::new_error(self.tcx, guar);
} }
} else {
self.found = Some(concrete_type);
} }
} }
} }
@ -287,54 +242,42 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
def_id: LocalDefId, def_id: LocalDefId,
owner_def_id: LocalDefId, owner_def_id: LocalDefId,
opaque_types_from: DefiningScopeKind,
) -> Ty<'tcx> { ) -> Ty<'tcx> {
let tables = tcx.typeck(owner_def_id); match opaque_types_from {
DefiningScopeKind::HirTypeck => {
// Check that all of the opaques we inferred during HIR are compatible. let tables = tcx.typeck(owner_def_id);
// FIXME: We explicitly don't check that the types inferred during HIR if let Some(guar) = tables.tainted_by_errors {
// typeck are compatible with the one that we infer during borrowck, Ty::new_error(tcx, guar)
// because that one actually sometimes has consts evaluated eagerly so } else if let Some(hidden_ty) = tables.concrete_opaque_types.get(&def_id) {
// using strict type equality will fail. hidden_ty.ty
let mut hir_opaque_ty: Option<ty::OpaqueHiddenType<'tcx>> = None;
if tables.tainted_by_errors.is_none() {
for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types {
if opaque_type_key.def_id != def_id {
continue;
}
let concrete_type = tcx.erase_regions(
hidden_type.remap_generic_params_to_declaration_params(opaque_type_key, tcx, true),
);
if let Some(prev) = &mut hir_opaque_ty {
if concrete_type.ty != prev.ty {
if let Ok(d) = prev.build_mismatch_error(&concrete_type, tcx) {
d.emit();
}
}
} else { } else {
hir_opaque_ty = Some(concrete_type); // FIXME(-Znext-solver): This should not be necessary and we should
// instead rely on inference variable fallback inside of typeck itself.
// We failed to resolve the opaque type or it
// resolves to itself. We interpret this as the
// no values of the hidden type ever being constructed,
// so we can just make the hidden type be `!`.
// For backwards compatibility reasons, we fall back to
// `()` until we the diverging default is changed.
Ty::new_diverging_default(tcx)
} }
} }
} DefiningScopeKind::MirBorrowck => {
let borrowck_result = tcx.mir_borrowck(owner_def_id);
let mir_opaque_ty = tcx.mir_borrowck(owner_def_id).concrete_opaque_types.get(&def_id).copied(); if let Some(guar) = borrowck_result.tainted_by_errors {
if let Some(mir_opaque_ty) = mir_opaque_ty { Ty::new_error(tcx, guar)
mir_opaque_ty.ty } else if let Some(hidden_ty) = borrowck_result.concrete_opaque_types.get(&def_id) {
} else if let Some(guar) = tables.tainted_by_errors { hidden_ty.ty
// Some error in the owner fn prevented us from populating } else {
// the `concrete_opaque_types` table. let hir_ty = tcx.type_of_opaque_hir_typeck(def_id).instantiate_identity();
Ty::new_error(tcx, guar) if let Err(guar) = hir_ty.error_reported() {
} else { Ty::new_error(tcx, guar)
// Fall back to the RPIT we inferred during HIR typeck } else {
if let Some(hir_opaque_ty) = hir_opaque_ty { hir_ty
hir_opaque_ty.ty }
} else { }
// We failed to resolve the opaque type or it
// resolves to itself. We interpret this as the
// no values of the hidden type ever being constructed,
// so we can just make the hidden type be `!`.
// For backwards compatibility reasons, we fall back to
// `()` until we the diverging default is changed.
Ty::new_diverging_default(tcx)
} }
} }
} }

View file

@ -12,10 +12,12 @@ use rustc_middle::span_bug;
use rustc_middle::traits::ObligationCause; use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
use rustc_middle::ty::{ use rustc_middle::ty::{
self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, fold_regions, self, DefiningScopeKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
TypeVisitableExt, fold_regions,
}; };
use rustc_span::{Span, sym}; use rustc_span::{Span, sym};
use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded; use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
use rustc_trait_selection::opaque_types::check_opaque_type_parameter_valid;
use rustc_trait_selection::solve; use rustc_trait_selection::solve;
use tracing::{debug, instrument}; use tracing::{debug, instrument};
@ -553,6 +555,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
#[instrument(skip(self), level = "debug")] #[instrument(skip(self), level = "debug")]
fn visit_opaque_types(&mut self) { fn visit_opaque_types(&mut self) {
let tcx = self.tcx();
// We clone the opaques instead of stealing them here as they are still used for // We clone the opaques instead of stealing them here as they are still used for
// normalization in the next generation trait solver. // normalization in the next generation trait solver.
// //
@ -575,16 +578,46 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
} }
} }
// Here we only detect impl trait definition conflicts when they if let Err(guar) = check_opaque_type_parameter_valid(
// are equal modulo regions. &self.fcx,
if let Some(last_opaque_ty) = opaque_type_key,
self.typeck_results.concrete_opaque_types.insert(opaque_type_key, hidden_type) hidden_type.span,
&& last_opaque_ty.ty != hidden_type.ty DefiningScopeKind::HirTypeck,
) {
self.typeck_results
.concrete_opaque_types
.insert(opaque_type_key.def_id, ty::OpaqueHiddenType::new_error(tcx, guar));
}
let hidden_type = hidden_type.remap_generic_params_to_declaration_params(
opaque_type_key,
tcx,
DefiningScopeKind::HirTypeck,
);
if let Some(prev) = self
.typeck_results
.concrete_opaque_types
.insert(opaque_type_key.def_id, hidden_type)
{ {
assert!(!self.fcx.next_trait_solver()); let entry = &mut self
if let Ok(d) = hidden_type.build_mismatch_error(&last_opaque_ty, self.tcx()) { .typeck_results
d.emit(); .concrete_opaque_types
.get_mut(&opaque_type_key.def_id)
.unwrap();
if prev.ty != hidden_type.ty {
if let Some(guar) = self.typeck_results.tainted_by_errors {
entry.ty = Ty::new_error(tcx, guar);
} else {
let (Ok(guar) | Err(guar)) =
prev.build_mismatch_error(&hidden_type, tcx).map(|d| d.emit());
entry.ty = Ty::new_error(tcx, guar);
}
} }
// Pick a better span if there is one.
// FIXME(oli-obk): collect multiple spans for better diagnostics down the road.
entry.span = prev.span.substitute_dummy(hidden_type.span);
} }
} }
} }

View file

@ -966,7 +966,8 @@ impl<'tcx> InferCtxt<'tcx> {
pub fn can_define_opaque_ty(&self, id: impl Into<DefId>) -> bool { pub fn can_define_opaque_ty(&self, id: impl Into<DefId>) -> bool {
debug_assert!(!self.next_trait_solver()); debug_assert!(!self.next_trait_solver());
match self.typing_mode() { match self.typing_mode() {
TypingMode::Analysis { defining_opaque_types } => { TypingMode::Analysis { defining_opaque_types }
| TypingMode::Borrowck { defining_opaque_types } => {
id.into().as_local().is_some_and(|def_id| defining_opaque_types.contains(&def_id)) id.into().as_local().is_some_and(|def_id| defining_opaque_types.contains(&def_id))
} }
// FIXME(#132279): This function is quite weird in post-analysis // FIXME(#132279): This function is quite weird in post-analysis
@ -1260,7 +1261,8 @@ impl<'tcx> InferCtxt<'tcx> {
// to handle them without proper canonicalization. This means we may cause cycle // to handle them without proper canonicalization. This means we may cause cycle
// errors and fail to reveal opaques while inside of bodies. We should rename this // errors and fail to reveal opaques while inside of bodies. We should rename this
// function and require explicit comments on all use-sites in the future. // function and require explicit comments on all use-sites in the future.
ty::TypingMode::Analysis { defining_opaque_types: _ } => { ty::TypingMode::Analysis { defining_opaque_types: _ }
| ty::TypingMode::Borrowck { defining_opaque_types: _ } => {
TypingMode::non_body_analysis() TypingMode::non_body_analysis()
} }
mode @ (ty::TypingMode::Coherence mode @ (ty::TypingMode::Coherence

View file

@ -12,7 +12,7 @@ use rustc_middle::ty::{
use rustc_span::Span; use rustc_span::Span;
use tracing::{debug, instrument}; use tracing::{debug, instrument};
use super::DefineOpaqueTypes; use super::{DefineOpaqueTypes, RegionVariableOrigin};
use crate::errors::OpaqueHiddenTypeDiag; use crate::errors::OpaqueHiddenTypeDiag;
use crate::infer::{InferCtxt, InferOk}; use crate::infer::{InferCtxt, InferOk};
use crate::traits::{self, Obligation, PredicateObligations}; use crate::traits::{self, Obligation, PredicateObligations};
@ -221,6 +221,7 @@ impl<'tcx> InferCtxt<'tcx> {
hidden_ty: Ty<'tcx>, hidden_ty: Ty<'tcx>,
goals: &mut Vec<Goal<'tcx, ty::Predicate<'tcx>>>, goals: &mut Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
) -> Result<(), TypeError<'tcx>> { ) -> Result<(), TypeError<'tcx>> {
let tcx = self.tcx;
// Ideally, we'd get the span where *this specific `ty` came // Ideally, we'd get the span where *this specific `ty` came
// from*, but right now we just use the span from the overall // from*, but right now we just use the span from the overall
// value being folded. In simple cases like `-> impl Foo`, // value being folded. In simple cases like `-> impl Foo`,
@ -231,7 +232,7 @@ impl<'tcx> InferCtxt<'tcx> {
// During intercrate we do not define opaque types but instead always // During intercrate we do not define opaque types but instead always
// force ambiguity unless the hidden type is known to not implement // force ambiguity unless the hidden type is known to not implement
// our trait. // our trait.
goals.push(Goal::new(self.tcx, param_env, ty::PredicateKind::Ambiguous)); goals.push(Goal::new(tcx, param_env, ty::PredicateKind::Ambiguous));
} }
ty::TypingMode::Analysis { .. } => { ty::TypingMode::Analysis { .. } => {
let prev = self let prev = self
@ -249,6 +250,36 @@ impl<'tcx> InferCtxt<'tcx> {
); );
} }
} }
ty::TypingMode::Borrowck { .. } => {
let prev = self
.inner
.borrow_mut()
.opaque_types()
.register(opaque_type_key, OpaqueHiddenType { ty: hidden_ty, span });
// We either equate the new hidden type with the previous entry or with the type
// inferred by HIR typeck.
let actual = prev.unwrap_or_else(|| {
let actual = tcx
.type_of_opaque_hir_typeck(opaque_type_key.def_id)
.instantiate(self.tcx, opaque_type_key.args);
let actual = ty::fold_regions(tcx, actual, |re, _dbi| match re.kind() {
ty::ReErased => {
self.next_region_var(RegionVariableOrigin::MiscVariable(span))
}
_ => re,
});
actual
});
goals.extend(
self.at(&ObligationCause::dummy_with_span(span), param_env)
.eq(DefineOpaqueTypes::Yes, hidden_ty, actual)?
.obligations
.into_iter()
.map(|obligation| obligation.as_goal()),
);
}
mode @ (ty::TypingMode::PostBorrowckAnalysis { .. } | ty::TypingMode::PostAnalysis) => { mode @ (ty::TypingMode::PostBorrowckAnalysis { .. } | ty::TypingMode::PostAnalysis) => {
bug!("insert hidden type in {mode:?}") bug!("insert hidden type in {mode:?}")
} }

View file

@ -267,6 +267,8 @@ rustc_queries! {
/// ///
/// This is a specialized instance of [`Self::type_of`] that detects query cycles. /// This is a specialized instance of [`Self::type_of`] that detects query cycles.
/// Unless `CyclePlaceholder` needs to be handled separately, call [`Self::type_of`] instead. /// Unless `CyclePlaceholder` needs to be handled separately, call [`Self::type_of`] instead.
/// This is used to improve the error message in cases where revealing the hidden type
/// for auto-trait leakage cycles.
/// ///
/// # Panics /// # Panics
/// ///
@ -278,6 +280,12 @@ rustc_queries! {
} }
cycle_stash cycle_stash
} }
query type_of_opaque_hir_typeck(key: LocalDefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> {
desc { |tcx|
"computing type of opaque `{path}` via HIR typeck",
path = tcx.def_path_str(key),
}
}
/// Returns whether the type alias given by `DefId` is lazy. /// Returns whether the type alias given by `DefId` is lazy.
/// ///

View file

@ -206,6 +206,9 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
fn type_of(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { fn type_of(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> {
self.type_of(def_id) self.type_of(def_id)
} }
fn type_of_opaque_hir_typeck(self, def_id: LocalDefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> {
self.type_of_opaque_hir_typeck(def_id)
}
type AdtDef = ty::AdtDef<'tcx>; type AdtDef = ty::AdtDef<'tcx>;
fn adt_def(self, adt_def_id: DefId) -> Self::AdtDef { fn adt_def(self, adt_def_id: DefId) -> Self::AdtDef {
@ -3248,6 +3251,11 @@ impl<'tcx> TyCtxt<'tcx> {
self.sess.opts.unstable_opts.next_solver.coherence self.sess.opts.unstable_opts.next_solver.coherence
} }
#[allow(rustc::bad_opt_access)]
pub fn use_typing_mode_borrowck(self) -> bool {
self.next_trait_solver_globally() || self.sess.opts.unstable_opts.typing_mode_borrowck
}
pub fn is_impl_trait_in_trait(self, def_id: DefId) -> bool { pub fn is_impl_trait_in_trait(self, def_id: DefId) -> bool {
self.opt_rpitit_info(def_id).is_some() self.opt_rpitit_info(def_id).is_some()
} }

View file

@ -48,7 +48,7 @@ use rustc_serialize::{Decodable, Encodable};
use rustc_session::lint::LintBuffer; use rustc_session::lint::LintBuffer;
pub use rustc_session::lint::RegisteredTools; pub use rustc_session::lint::RegisteredTools;
use rustc_span::hygiene::MacroKind; use rustc_span::hygiene::MacroKind;
use rustc_span::{ExpnId, ExpnKind, Ident, Span, Symbol, kw, sym}; use rustc_span::{DUMMY_SP, ExpnId, ExpnKind, Ident, Span, Symbol, kw, sym};
pub use rustc_type_ir::relate::VarianceDiagInfo; pub use rustc_type_ir::relate::VarianceDiagInfo;
pub use rustc_type_ir::*; pub use rustc_type_ir::*;
use tracing::{debug, instrument}; use tracing::{debug, instrument};
@ -782,7 +782,22 @@ pub struct OpaqueHiddenType<'tcx> {
pub ty: Ty<'tcx>, pub ty: Ty<'tcx>,
} }
/// Whether we're currently in HIR typeck or MIR borrowck.
#[derive(Debug, Clone, Copy)]
pub enum DefiningScopeKind {
/// During writeback in typeck, we don't care about regions and simply
/// erase them. This means we also don't check whether regions are
/// universal in the opaque type key. This will only be checked in
/// MIR borrowck.
HirTypeck,
MirBorrowck,
}
impl<'tcx> OpaqueHiddenType<'tcx> { impl<'tcx> OpaqueHiddenType<'tcx> {
pub fn new_error(tcx: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> OpaqueHiddenType<'tcx> {
OpaqueHiddenType { span: DUMMY_SP, ty: Ty::new_error(tcx, guar) }
}
pub fn build_mismatch_error( pub fn build_mismatch_error(
&self, &self,
other: &Self, other: &Self,
@ -808,8 +823,7 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
self, self,
opaque_type_key: OpaqueTypeKey<'tcx>, opaque_type_key: OpaqueTypeKey<'tcx>,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
// typeck errors have subpar spans for opaque types, so delay error reporting until borrowck. defining_scope_kind: DefiningScopeKind,
ignore_errors: bool,
) -> Self { ) -> Self {
let OpaqueTypeKey { def_id, args } = opaque_type_key; let OpaqueTypeKey { def_id, args } = opaque_type_key;
@ -828,10 +842,19 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
let map = args.iter().zip(id_args).collect(); let map = args.iter().zip(id_args).collect();
debug!("map = {:#?}", map); debug!("map = {:#?}", map);
// Convert the type from the function into a type valid outside // Convert the type from the function into a type valid outside by mapping generic
// the function, by replacing invalid regions with 'static, // parameters to into the context of the opaque.
// after producing an error for each of them. //
self.fold_with(&mut opaque_types::ReverseMapper::new(tcx, map, self.span, ignore_errors)) // We erase regions when doing this during HIR typeck.
let this = match defining_scope_kind {
DefiningScopeKind::HirTypeck => tcx.erase_regions(self),
DefiningScopeKind::MirBorrowck => self,
};
let result = this.fold_with(&mut opaque_types::ReverseMapper::new(tcx, map, self.span));
if cfg!(debug_assertions) && matches!(defining_scope_kind, DefiningScopeKind::HirTypeck) {
assert_eq!(result.ty, tcx.erase_regions(result.ty));
}
result
} }
} }

View file

@ -20,12 +20,6 @@ pub(super) struct ReverseMapper<'tcx> {
/// for an explanation of this field. /// for an explanation of this field.
do_not_error: bool, do_not_error: bool,
/// We do not want to emit any errors in typeck because
/// the spans in typeck are subpar at the moment.
/// Borrowck will do the same work again (this time with
/// lifetime information) and thus report better errors.
ignore_errors: bool,
/// Span of function being checked. /// Span of function being checked.
span: Span, span: Span,
} }
@ -35,9 +29,8 @@ impl<'tcx> ReverseMapper<'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>, map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
span: Span, span: Span,
ignore_errors: bool,
) -> Self { ) -> Self {
Self { tcx, map, do_not_error: false, ignore_errors, span } Self { tcx, map, do_not_error: false, span }
} }
fn fold_kind_no_missing_regions_error(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> { fn fold_kind_no_missing_regions_error(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
@ -176,20 +169,18 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
Some(u) => panic!("type mapped to unexpected kind: {u:?}"), Some(u) => panic!("type mapped to unexpected kind: {u:?}"),
None => { None => {
debug!(?param, ?self.map); debug!(?param, ?self.map);
if !self.ignore_errors { let guar = self
self.tcx .tcx
.dcx() .dcx()
.struct_span_err( .struct_span_err(
self.span, self.span,
format!( format!(
"type parameter `{ty}` is part of concrete type but not \ "type parameter `{ty}` is part of concrete type but not \
used in parameter list for the `impl Trait` type alias" used in parameter list for the `impl Trait` type alias"
), ),
) )
.emit(); .emit();
} Ty::new_error(self.tcx, guar)
Ty::new_misc_error(self.tcx)
} }
} }
} }
@ -217,8 +208,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
ct: ct.to_string(), ct: ct.to_string(),
span: self.span, span: self.span,
}) })
.emit_unless(self.ignore_errors); .emit();
ty::Const::new_error(self.tcx, guar) ty::Const::new_error(self.tcx, guar)
} }
} }

View file

@ -158,7 +158,7 @@ pub struct TypeckResults<'tcx> {
/// We also store the type here, so that the compiler can use it as a hint /// We also store the type here, so that the compiler can use it as a hint
/// for figuring out hidden types, even if they are only set in dead code /// for figuring out hidden types, even if they are only set in dead code
/// (which doesn't show up in MIR). /// (which doesn't show up in MIR).
pub concrete_opaque_types: FxIndexMap<ty::OpaqueTypeKey<'tcx>, ty::OpaqueHiddenType<'tcx>>, pub concrete_opaque_types: FxIndexMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
/// Tracks the minimum captures required for a closure; /// Tracks the minimum captures required for a closure;
/// see `MinCaptureInformationMap` for more details. /// see `MinCaptureInformationMap` for more details.

View file

@ -330,6 +330,7 @@ where
// During analysis, opaques are rigid unless they may be defined by // During analysis, opaques are rigid unless they may be defined by
// the current body. // the current body.
TypingMode::Analysis { defining_opaque_types: non_rigid_opaques } TypingMode::Analysis { defining_opaque_types: non_rigid_opaques }
| TypingMode::Borrowck { defining_opaque_types: non_rigid_opaques }
| TypingMode::PostBorrowckAnalysis { defined_opaque_types: non_rigid_opaques } => { | TypingMode::PostBorrowckAnalysis { defined_opaque_types: non_rigid_opaques } => {
!def_id.as_local().is_some_and(|def_id| non_rigid_opaques.contains(&def_id)) !def_id.as_local().is_some_and(|def_id| non_rigid_opaques.contains(&def_id))
} }

View file

@ -96,6 +96,42 @@ where
); );
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
} }
// Very similar to `TypingMode::Analysis` with some notably differences:
// - we accept opaque types even if they have non-universal arguments
// - we do a structural lookup instead of semantically unifying regions
// - the hidden type starts out as the type from HIR typeck with fresh region
// variables instead of a fully unconstrained inference variable
TypingMode::Borrowck { defining_opaque_types } => {
let Some(def_id) = opaque_ty
.def_id
.as_local()
.filter(|&def_id| defining_opaque_types.contains(&def_id))
else {
self.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
};
let opaque_type_key = ty::OpaqueTypeKey { def_id, args: opaque_ty.args };
let actual = self
.register_hidden_type_in_storage(opaque_type_key, expected)
.unwrap_or_else(|| {
let actual =
cx.type_of_opaque_hir_typeck(def_id).instantiate(cx, opaque_ty.args);
let actual = fold_regions(cx, actual, |re, _dbi| match re.kind() {
ty::ReErased => self.next_region_var(),
_ => re,
});
actual
});
self.eq(goal.param_env, expected, actual)?;
self.add_item_bounds_for_hidden_type(
def_id.into(),
opaque_ty.args,
goal.param_env,
expected,
);
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
TypingMode::PostBorrowckAnalysis { defined_opaque_types } => { TypingMode::PostBorrowckAnalysis { defined_opaque_types } => {
let Some(def_id) = opaque_ty let Some(def_id) = opaque_ty
.def_id .def_id

View file

@ -62,6 +62,7 @@ where
response_no_constraints(cx, input, Certainty::overflow(false)) response_no_constraints(cx, input, Certainty::overflow(false))
} }
TypingMode::Analysis { .. } TypingMode::Analysis { .. }
| TypingMode::Borrowck { .. }
| TypingMode::PostBorrowckAnalysis { .. } | TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis => Err(NoSolution), | TypingMode::PostAnalysis => Err(NoSolution),
}, },

View file

@ -72,6 +72,7 @@ where
(ty::ImplPolarity::Reservation, _) => match ecx.typing_mode() { (ty::ImplPolarity::Reservation, _) => match ecx.typing_mode() {
TypingMode::Coherence => Certainty::AMBIGUOUS, TypingMode::Coherence => Certainty::AMBIGUOUS,
TypingMode::Analysis { .. } TypingMode::Analysis { .. }
| TypingMode::Borrowck { .. }
| TypingMode::PostBorrowckAnalysis { .. } | TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis => return Err(NoSolution), | TypingMode::PostAnalysis => return Err(NoSolution),
}, },

View file

@ -135,7 +135,10 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
/// Returns the hidden type corresponding to this key if the body under analysis is allowed to /// Returns the hidden type corresponding to this key if the body under analysis is allowed to
/// know it. /// know it.
fn reveal_opaque_key(&self, key: OpaqueTypeKey<'tcx>) -> Option<Ty<'tcx>> { fn reveal_opaque_key(&self, key: OpaqueTypeKey<'tcx>) -> Option<Ty<'tcx>> {
self.typeck_results.concrete_opaque_types.get(&key).map(|x| x.ty) self.typeck_results
.concrete_opaque_types
.get(&key.def_id)
.map(|x| ty::EarlyBinder::bind(x.ty).instantiate(self.tcx, key.args))
} }
// This can take a non-revealed `Ty` because it reveals opaques itself. // This can take a non-revealed `Ty` because it reveals opaques itself.
pub fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool { pub fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {

View file

@ -2553,6 +2553,9 @@ written to standard error output)"),
"in diagnostics, use heuristics to shorten paths referring to items"), "in diagnostics, use heuristics to shorten paths referring to items"),
tune_cpu: Option<String> = (None, parse_opt_string, [TRACKED], tune_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
"select processor to schedule for (`rustc --print target-cpus` for details)"), "select processor to schedule for (`rustc --print target-cpus` for details)"),
#[rustc_lint_opt_deny_field_access("use `TyCtxt::use_typing_mode_borrowck` instead of this field")]
typing_mode_borrowck: bool = (false, parse_bool, [TRACKED],
"enable `TypingMode::Borrowck`, changing the way opaque types are handled during MIR borrowck"),
#[rustc_lint_opt_deny_field_access("use `Session::ub_checks` instead of this field")] #[rustc_lint_opt_deny_field_access("use `Session::ub_checks` instead of this field")]
ub_checks: Option<bool> = (None, parse_opt_bool, [TRACKED], ub_checks: Option<bool> = (None, parse_opt_bool, [TRACKED],
"emit runtime checks for Undefined Behavior (default: -Cdebug-assertions)"), "emit runtime checks for Undefined Behavior (default: -Cdebug-assertions)"),

View file

@ -4,7 +4,7 @@ use rustc_hir::def_id::LocalDefId;
use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_middle::ty::{ use rustc_middle::ty::{
self, GenericArgKind, GenericArgs, OpaqueTypeKey, TyCtxt, TypeVisitableExt, self, DefiningScopeKind, GenericArgKind, GenericArgs, OpaqueTypeKey, TyCtxt, TypeVisitableExt,
TypingMode, fold_regions, TypingMode, fold_regions,
}; };
use rustc_span::{ErrorGuaranteed, Span}; use rustc_span::{ErrorGuaranteed, Span};
@ -21,19 +21,36 @@ pub fn check_opaque_type_parameter_valid<'tcx>(
infcx: &InferCtxt<'tcx>, infcx: &InferCtxt<'tcx>,
opaque_type_key: OpaqueTypeKey<'tcx>, opaque_type_key: OpaqueTypeKey<'tcx>,
span: Span, span: Span,
defining_scope_kind: DefiningScopeKind,
) -> Result<(), ErrorGuaranteed> { ) -> Result<(), ErrorGuaranteed> {
let tcx = infcx.tcx; let tcx = infcx.tcx;
let opaque_generics = tcx.generics_of(opaque_type_key.def_id); let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
let opaque_env = LazyOpaqueTyEnv::new(tcx, opaque_type_key.def_id); let opaque_env = LazyOpaqueTyEnv::new(tcx, opaque_type_key.def_id);
let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default(); let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default();
// Avoid duplicate errors in case the opaque has already been malformed in
// HIR typeck.
if let DefiningScopeKind::MirBorrowck = defining_scope_kind {
if let Err(guar) = infcx
.tcx
.type_of_opaque_hir_typeck(opaque_type_key.def_id)
.instantiate_identity()
.error_reported()
{
return Err(guar);
}
}
for (i, arg) in opaque_type_key.iter_captured_args(tcx) { for (i, arg) in opaque_type_key.iter_captured_args(tcx) {
let arg_is_param = match arg.unpack() { let arg_is_param = match arg.unpack() {
GenericArgKind::Lifetime(lt) => match defining_scope_kind {
DefiningScopeKind::HirTypeck => continue,
DefiningScopeKind::MirBorrowck => {
matches!(*lt, ty::ReEarlyParam(_) | ty::ReLateParam(_))
|| (lt.is_static() && opaque_env.param_equal_static(i))
}
},
GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)), GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
GenericArgKind::Lifetime(lt) => {
matches!(*lt, ty::ReEarlyParam(_) | ty::ReLateParam(_))
|| (lt.is_static() && opaque_env.param_equal_static(i))
}
GenericArgKind::Const(ct) => matches!(ct.kind(), ty::ConstKind::Param(_)), GenericArgKind::Const(ct) => matches!(ct.kind(), ty::ConstKind::Param(_)),
}; };

View file

@ -195,6 +195,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
match self.typing_mode() { match self.typing_mode() {
TypingMode::Coherence TypingMode::Coherence
| TypingMode::Analysis { .. } | TypingMode::Analysis { .. }
| TypingMode::Borrowck { .. }
| TypingMode::PostBorrowckAnalysis { .. } => false, | TypingMode::PostBorrowckAnalysis { .. } => false,
TypingMode::PostAnalysis => { TypingMode::PostAnalysis => {
let poly_trait_ref = self.resolve_vars_if_possible(goal_trait_ref); let poly_trait_ref = self.resolve_vars_if_possible(goal_trait_ref);

View file

@ -130,6 +130,7 @@ pub(super) fn needs_normalization<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
// FIXME(#132279): We likely want to reveal opaques during post borrowck analysis // FIXME(#132279): We likely want to reveal opaques during post borrowck analysis
TypingMode::Coherence TypingMode::Coherence
| TypingMode::Analysis { .. } | TypingMode::Analysis { .. }
| TypingMode::Borrowck { .. }
| TypingMode::PostBorrowckAnalysis { .. } => flags.remove(ty::TypeFlags::HAS_TY_OPAQUE), | TypingMode::PostBorrowckAnalysis { .. } => flags.remove(ty::TypeFlags::HAS_TY_OPAQUE),
TypingMode::PostAnalysis => {} TypingMode::PostAnalysis => {}
} }
@ -226,6 +227,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
// FIXME(#132279): We likely want to reveal opaques during post borrowck analysis // FIXME(#132279): We likely want to reveal opaques during post borrowck analysis
TypingMode::Coherence TypingMode::Coherence
| TypingMode::Analysis { .. } | TypingMode::Analysis { .. }
| TypingMode::Borrowck { .. }
| TypingMode::PostBorrowckAnalysis { .. } => ty.super_fold_with(self), | TypingMode::PostBorrowckAnalysis { .. } => ty.super_fold_with(self),
TypingMode::PostAnalysis => { TypingMode::PostAnalysis => {
let recursion_limit = self.cx().recursion_limit(); let recursion_limit = self.cx().recursion_limit();

View file

@ -952,6 +952,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
match selcx.infcx.typing_mode() { match selcx.infcx.typing_mode() {
TypingMode::Coherence TypingMode::Coherence
| TypingMode::Analysis { .. } | TypingMode::Analysis { .. }
| TypingMode::Borrowck { .. }
| TypingMode::PostBorrowckAnalysis { .. } => { | TypingMode::PostBorrowckAnalysis { .. } => {
debug!( debug!(
assoc_ty = ?selcx.tcx().def_path_str(node_item.item.def_id), assoc_ty = ?selcx.tcx().def_path_str(node_item.item.def_id),

View file

@ -216,6 +216,7 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'a, 'tcx> {
match self.infcx.typing_mode() { match self.infcx.typing_mode() {
TypingMode::Coherence TypingMode::Coherence
| TypingMode::Analysis { .. } | TypingMode::Analysis { .. }
| TypingMode::Borrowck { .. }
| TypingMode::PostBorrowckAnalysis { .. } => ty.try_super_fold_with(self)?, | TypingMode::PostBorrowckAnalysis { .. } => ty.try_super_fold_with(self)?,
TypingMode::PostAnalysis => { TypingMode::PostAnalysis => {

View file

@ -1446,6 +1446,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
match self.infcx.typing_mode() { match self.infcx.typing_mode() {
TypingMode::Coherence => {} TypingMode::Coherence => {}
TypingMode::Analysis { .. } TypingMode::Analysis { .. }
| TypingMode::Borrowck { .. }
| TypingMode::PostBorrowckAnalysis { .. } | TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis => return Ok(()), | TypingMode::PostAnalysis => return Ok(()),
} }
@ -1491,7 +1492,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// However, if we disqualify *all* goals from being cached, perf suffers. // However, if we disqualify *all* goals from being cached, perf suffers.
// This is likely fixed by better caching in general in the new solver. // This is likely fixed by better caching in general in the new solver.
// See: <https://github.com/rust-lang/rust/issues/132064>. // See: <https://github.com/rust-lang/rust/issues/132064>.
TypingMode::Analysis { defining_opaque_types } => { TypingMode::Analysis { defining_opaque_types }
| TypingMode::Borrowck { defining_opaque_types } => {
defining_opaque_types.is_empty() || !pred.has_opaque_types() defining_opaque_types.is_empty() || !pred.has_opaque_types()
} }
// The hidden types of `defined_opaque_types` is not local to the current // The hidden types of `defined_opaque_types` is not local to the current

View file

@ -149,6 +149,7 @@ fn resolve_associated_item<'tcx>(
match typing_env.typing_mode { match typing_env.typing_mode {
ty::TypingMode::Coherence ty::TypingMode::Coherence
| ty::TypingMode::Analysis { .. } | ty::TypingMode::Analysis { .. }
| ty::TypingMode::Borrowck { .. }
| ty::TypingMode::PostBorrowckAnalysis { .. } => false, | ty::TypingMode::PostBorrowckAnalysis { .. } => false,
ty::TypingMode::PostAnalysis => !trait_ref.still_further_specializable(), ty::TypingMode::PostAnalysis => !trait_ref.still_further_specializable(),
} }

View file

@ -66,6 +66,14 @@ pub enum TypingMode<I: Interner> {
/// } /// }
/// ``` /// ```
Analysis { defining_opaque_types: I::DefiningOpaqueTypes }, Analysis { defining_opaque_types: I::DefiningOpaqueTypes },
/// The behavior during MIR borrowck is identical to `TypingMode::Analysis`
/// except that the initial value for opaque types is the type computed during
/// HIR typeck with unique unconstrained region inference variables.
///
/// This is currently only used with by the new solver as it results in new
/// non-universal defining uses of opaque types, which is a breaking change.
/// See tests/ui/impl-trait/non-defining-use/as-projection-term.rs.
Borrowck { defining_opaque_types: I::DefiningOpaqueTypes },
/// Any analysis after borrowck for a given body should be able to use all the /// Any analysis after borrowck for a given body should be able to use all the
/// hidden types defined by borrowck, without being able to define any new ones. /// hidden types defined by borrowck, without being able to define any new ones.
/// ///
@ -95,6 +103,10 @@ impl<I: Interner> TypingMode<I> {
TypingMode::Analysis { defining_opaque_types: cx.opaque_types_defined_by(body_def_id) } TypingMode::Analysis { defining_opaque_types: cx.opaque_types_defined_by(body_def_id) }
} }
pub fn borrowck(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
TypingMode::Borrowck { defining_opaque_types: cx.opaque_types_defined_by(body_def_id) }
}
pub fn post_borrowck_analysis(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> { pub fn post_borrowck_analysis(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
TypingMode::PostBorrowckAnalysis { TypingMode::PostBorrowckAnalysis {
defined_opaque_types: cx.opaque_types_defined_by(body_def_id), defined_opaque_types: cx.opaque_types_defined_by(body_def_id),

View file

@ -149,6 +149,8 @@ pub trait Interner:
) -> Option<Self::VariancesOf>; ) -> Option<Self::VariancesOf>;
fn type_of(self, def_id: Self::DefId) -> ty::EarlyBinder<Self, Self::Ty>; fn type_of(self, def_id: Self::DefId) -> ty::EarlyBinder<Self, Self::Ty>;
fn type_of_opaque_hir_typeck(self, def_id: Self::LocalDefId)
-> ty::EarlyBinder<Self, Self::Ty>;
type AdtDef: AdtDef<Self>; type AdtDef: AdtDef<Self>;
fn adt_def(self, adt_def_id: Self::DefId) -> Self::AdtDef; fn adt_def(self, adt_def_id: Self::DefId) -> Self::AdtDef;

View file

@ -137,6 +137,7 @@ where
Ok(a) Ok(a)
} }
TypingMode::Analysis { .. } TypingMode::Analysis { .. }
| TypingMode::Borrowck { .. }
| TypingMode::PostBorrowckAnalysis { .. } | TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis => structurally_relate_tys(relation, a, b), | TypingMode::PostAnalysis => structurally_relate_tys(relation, a, b),
} }

View file

@ -1,19 +0,0 @@
//@ known-bug: #112201
pub fn compose(
f1: impl FnOnce(f64) -> f64 + Clone,
f2: impl FnOnce(f64) -> f64 + Clone,
) -> impl FnOnce(f64) -> f64 + Clone {
move |x| f1(f2(x))
}
fn repeat_helper(
f: impl FnOnce(f64) -> f64 + Clone,
res: impl FnOnce(f64) -> f64 + Clone,
times: usize,
) -> impl FnOnce(f64) -> f64 + Clone {
return res;
repeat_helper(f.clone(), compose(f, res), times - 1)
}
fn main() {}

View file

@ -1,6 +0,0 @@
//@ known-bug: #137751
//@ compile-flags: --edition=2021 -Znext-solver=globally
async fn test() {
Box::pin(test()).await;
}
fn main() {}

View file

@ -35,11 +35,11 @@ note: ...which requires type-checking `foo::{closure#0}`...
LL | move |_: ()| { LL | move |_: ()| {
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^
= note: ...which again requires type-checking `foo`, completing the cycle = note: ...which again requires type-checking `foo`, completing the cycle
note: cycle used when computing type of opaque `foo::{opaque#0}` note: cycle used when match-checking `foo`
--> $DIR/clone-rpit.rs:13:25 --> $DIR/clone-rpit.rs:13:1
| |
LL | pub fn foo<'a, 'b>() -> impl Clone { LL | pub fn foo<'a, 'b>() -> impl Clone {
| ^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -15,8 +15,8 @@ pub trait Trait2 {
impl<'c, S: Trait2> Trait2 for &'c mut S { impl<'c, S: Trait2> Trait2 for &'c mut S {
type FooFuture<'a> = impl Trait1; type FooFuture<'a> = impl Trait1;
//~^ ERROR unconstrained opaque type
fn foo<'a>() -> Self::FooFuture<'a> { fn foo<'a>() -> Self::FooFuture<'a> {
//~^ ERROR item does not constrain `<&'c mut S as Trait2>::FooFuture::{opaque#0}`
Struct(unimplemented!()) Struct(unimplemented!())
} }
} }

View file

@ -1,10 +1,15 @@
error: unconstrained opaque type error: item does not constrain `<&'c mut S as Trait2>::FooFuture::{opaque#0}`
--> $DIR/issue-87258_a.rs:18:8
|
LL | fn foo<'a>() -> Self::FooFuture<'a> {
| ^^^
|
= note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
note: this opaque type is supposed to be constrained
--> $DIR/issue-87258_a.rs:17:26 --> $DIR/issue-87258_a.rs:17:26
| |
LL | type FooFuture<'a> = impl Trait1; LL | type FooFuture<'a> = impl Trait1;
| ^^^^^^^^^^^ | ^^^^^^^^^^^
|
= note: `FooFuture` must be used in combination with a concrete type within the same impl
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -14,12 +14,12 @@ pub trait Trait2 {
} }
type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1; type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1;
//~^ ERROR unconstrained opaque type
impl<'c, S: Trait2> Trait2 for &'c mut S { impl<'c, S: Trait2> Trait2 for &'c mut S {
type FooFuture<'a> = Helper<'c, 'a, S>; type FooFuture<'a> = Helper<'c, 'a, S>;
#[define_opaque(Helper)] #[define_opaque(Helper)]
fn foo<'a>() -> Self::FooFuture<'a> { fn foo<'a>() -> Self::FooFuture<'a> {
//~^ ERROR item does not constrain `Helper::{opaque#0}`
Struct(unimplemented!()) Struct(unimplemented!())
} }
} }

View file

@ -1,10 +1,15 @@
error: unconstrained opaque type error: item does not constrain `Helper::{opaque#0}`
--> $DIR/issue-87258_b.rs:21:8
|
LL | fn foo<'a>() -> Self::FooFuture<'a> {
| ^^^
|
= note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
note: this opaque type is supposed to be constrained
--> $DIR/issue-87258_b.rs:16:49 --> $DIR/issue-87258_b.rs:16:49
| |
LL | type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1; LL | type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1;
| ^^^^^^^^^^^ | ^^^^^^^^^^^
|
= note: `Helper` must be used in combination with a concrete type within the same crate
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -1,18 +1,5 @@
error: item does not constrain `Foo::{opaque#0}`
--> $DIR/norm-before-method-resolution-opaque-type.rs:17:4
|
LL | fn weird_bound<X>(x: &<X as Trait<'static>>::Out<Foo>) -> X
| ^^^^^^^^^^^
|
= note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
note: this opaque type is supposed to be constrained
--> $DIR/norm-before-method-resolution-opaque-type.rs:14:12
|
LL | type Foo = impl Sized;
| ^^^^^^^^^^
error[E0507]: cannot move out of `*x` which is behind a shared reference error[E0507]: cannot move out of `*x` which is behind a shared reference
--> $DIR/norm-before-method-resolution-opaque-type.rs:23:13 --> $DIR/norm-before-method-resolution-opaque-type.rs:22:13
| |
LL | let x = *x; LL | let x = *x;
| ^^ move occurs because `*x` has type `<X as Trait<'_>>::Out<Foo>`, which does not implement the `Copy` trait | ^^ move occurs because `*x` has type `<X as Trait<'_>>::Out<Foo>`, which does not implement the `Copy` trait
@ -23,6 +10,6 @@ LL - let x = *x;
LL + let x = x; LL + let x = x;
| |
error: aborting due to 2 previous errors error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0507`. For more information about this error, try `rustc --explain E0507`.

View file

@ -15,7 +15,6 @@ type Foo = impl Sized;
#[define_opaque(Foo)] #[define_opaque(Foo)]
fn weird_bound<X>(x: &<X as Trait<'static>>::Out<Foo>) -> X fn weird_bound<X>(x: &<X as Trait<'static>>::Out<Foo>) -> X
//[old]~^ ERROR: item does not constrain
where where
for<'a> X: Trait<'a>, for<'a> X: Trait<'a>,
for<'a> <X as Trait<'a>>::Out<()>: Copy, for<'a> <X as Trait<'a>>::Out<()>: Copy,

View file

@ -13,6 +13,7 @@ impl<S: Default> Bar for S {
//~^ ERROR impl has stricter requirements than trait //~^ ERROR impl has stricter requirements than trait
//~| ERROR the trait bound `S: Copy` is not satisfied in `(S, T)` [E0277] //~| ERROR the trait bound `S: Copy` is not satisfied in `(S, T)` [E0277]
//~| ERROR the trait bound `T: Copy` is not satisfied in `(S, T)` [E0277] //~| ERROR the trait bound `T: Copy` is not satisfied in `(S, T)` [E0277]
//~| ERROR type parameter `T` is part of concrete type
(S::default(), T::default()) (S::default(), T::default())
} }
} }

View file

@ -37,7 +37,13 @@ help: consider further restricting type parameter `T` with trait `Copy`
LL | fn foo<T: Default + std::marker::Copy>() -> Self::E { LL | fn foo<T: Default + std::marker::Copy>() -> Self::E {
| +++++++++++++++++++ | +++++++++++++++++++
error: aborting due to 3 previous errors error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
--> $DIR/issue-55872-1.rs:12:29
|
LL | fn foo<T: Default>() -> Self::E {
| ^^^^^^^
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0276, E0277. Some errors have detailed explanations: E0276, E0277.
For more information about an error, try `rustc --explain E0276`. For more information about an error, try `rustc --explain E0276`.

View file

@ -11,9 +11,9 @@ pub trait Bar {
impl<S> Bar for S { impl<S> Bar for S {
type E = impl std::marker::Send; type E = impl std::marker::Send;
fn foo<T>() -> Self::E { fn foo<T>() -> Self::E {
async {}
//~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
//~| ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias //~| ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
async {}
} }
} }

View file

@ -1,14 +1,14 @@
error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
--> $DIR/issue-55872-2.rs:14:9 --> $DIR/issue-55872-2.rs:13:20
| |
LL | async {} LL | fn foo<T>() -> Self::E {
| ^^^^^^^^ | ^^^^^^^
error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
--> $DIR/issue-55872-2.rs:14:9 --> $DIR/issue-55872-2.rs:13:20
| |
LL | async {} LL | fn foo<T>() -> Self::E {
| ^^^^^^^^ | ^^^^^^^
| |
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

View file

@ -13,6 +13,7 @@ impl<S> Bar for S {
type E = impl std::marker::Copy; type E = impl std::marker::Copy;
fn foo<T>() -> Self::E { fn foo<T>() -> Self::E {
//~^ ERROR : Copy` is not satisfied [E0277] //~^ ERROR : Copy` is not satisfied [E0277]
//~| ERROR type parameter `T` is part of concrete type
async {} async {}
} }
} }

View file

@ -1,12 +1,18 @@
error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:16:9: 16:14}: Copy` is not satisfied error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:17:9: 17:14}: Copy` is not satisfied
--> $DIR/issue-55872-3.rs:14:20 --> $DIR/issue-55872-3.rs:14:20
| |
LL | fn foo<T>() -> Self::E { LL | fn foo<T>() -> Self::E {
| ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:16:9: 16:14}` | ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:17:9: 17:14}`
LL | ...
LL | async {} LL | async {}
| -------- return type was inferred to be `{async block@$DIR/issue-55872-3.rs:16:9: 16:14}` here | -------- return type was inferred to be `{async block@$DIR/issue-55872-3.rs:17:9: 17:14}` here
error: aborting due to 1 previous error error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
--> $DIR/issue-55872-3.rs:14:20
|
LL | fn foo<T>() -> Self::E {
| ^^^^^^^
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

@ -10,8 +10,8 @@ impl<S> Bar for S {
type E = impl Copy; type E = impl Copy;
fn foo<T>() -> Self::E { fn foo<T>() -> Self::E {
|| ()
//~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
|| ()
} }
} }

View file

@ -1,8 +1,8 @@
error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
--> $DIR/issue-55872.rs:13:9 --> $DIR/issue-55872.rs:12:20
| |
LL | || () LL | fn foo<T>() -> Self::E {
| ^^^^^ | ^^^^^^^
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -7,8 +7,7 @@ fn main() {
fn test<T: Display>(t: T, recurse: bool) -> impl Display { fn test<T: Display>(t: T, recurse: bool) -> impl Display {
let f = || { let f = || {
let i: u32 = test::<i32>(-1, false); let i: u32 = test::<i32>(-1, false);
//~^ ERROR concrete type differs from previous defining opaque type use //~^ ERROR expected generic type parameter, found `i32`
//~| ERROR expected generic type parameter, found `i32`
println!("{i}"); println!("{i}");
}; };
if recurse { if recurse {

View file

@ -1,15 +1,3 @@
error: concrete type differs from previous defining opaque type use
--> $DIR/issue-99073-2.rs:9:22
|
LL | let i: u32 = test::<i32>(-1, false);
| ^^^^^^^^^^^^^^^^^^^^^^ expected `T`, got `u32`
|
note: previous use here
--> $DIR/issue-99073-2.rs:7:45
|
LL | fn test<T: Display>(t: T, recurse: bool) -> impl Display {
| ^^^^^^^^^^^^
error[E0792]: expected generic type parameter, found `i32` error[E0792]: expected generic type parameter, found `i32`
--> $DIR/issue-99073-2.rs:9:22 --> $DIR/issue-99073-2.rs:9:22
| |
@ -19,6 +7,6 @@ LL | let f = || {
LL | let i: u32 = test::<i32>(-1, false); LL | let i: u32 = test::<i32>(-1, false);
| ^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0792`. For more information about this error, try `rustc --explain E0792`.

View file

@ -4,6 +4,5 @@ fn main() {
fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() { fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() {
move || f(fix(&f)) move || f(fix(&f))
//~^ ERROR concrete type differs from previous defining opaque type use //~^ ERROR expected generic type parameter, found `&F`
//~| ERROR expected generic type parameter, found `&F`
} }

View file

@ -1,23 +1,11 @@
error: concrete type differs from previous defining opaque type use
--> $DIR/issue-99073.rs:6:13
|
LL | move || f(fix(&f))
| ^^^^^^^ expected `{closure@$DIR/issue-99073.rs:6:3: 6:10}`, got `G`
|
note: previous use here
--> $DIR/issue-99073.rs:5:36
|
LL | fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() {
| ^^^^^^^^^
error[E0792]: expected generic type parameter, found `&F` error[E0792]: expected generic type parameter, found `&F`
--> $DIR/issue-99073.rs:6:11 --> $DIR/issue-99073.rs:6:13
| |
LL | fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() { LL | fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() {
| - this generic parameter must be used with a generic type parameter | - this generic parameter must be used with a generic type parameter
LL | move || f(fix(&f)) LL | move || f(fix(&f))
| ^^^^^^^^^^ | ^^^^^^^
error: aborting due to 2 previous errors error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0792`. For more information about this error, try `rustc --explain E0792`.

View file

@ -0,0 +1,17 @@
// Regression test for #112201. This recursive call previously meant that
// we delay an error when checking opaques at the end of writeback but don't
// encounter that incorrect defining use during borrowck as it's in dead code.
pub fn wrap<T>(x: T) -> impl Sized {
x
}
fn repeat_helper<T>(x: T) -> impl Sized {
return x;
repeat_helper(wrap(x))
//~^ ERROR expected generic type parameter, found `impl Sized`
//~| ERROR type parameter `T` is part of concrete type
}
fn main() {}

View file

@ -0,0 +1,18 @@
error[E0792]: expected generic type parameter, found `impl Sized`
--> $DIR/fuzzer-ice-issue-112201.rs:11:5
|
LL | fn repeat_helper<T>(x: T) -> impl Sized {
| - this generic parameter must be used with a generic type parameter
LL | return x;
LL | repeat_helper(wrap(x))
| ^^^^^^^^^^^^^^^^^^^^^^
error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
--> $DIR/fuzzer-ice-issue-112201.rs:11:5
|
LL | repeat_helper(wrap(x))
| ^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0792`.

View file

@ -29,7 +29,6 @@ where
F: FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O> + 'f, F: FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O> + 'f,
{ {
f f
//~^ ERROR expected generic lifetime parameter, found `'_`
} }
impl Context { impl Context {
@ -39,7 +38,6 @@ impl Context {
&self, &self,
f: impl FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O>, f: impl FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O>,
) -> TransactionResult<O> { ) -> TransactionResult<O> {
//~^ ERROR expected generic lifetime parameter, found `'_`
let mut conn = Connection {}; let mut conn = Connection {};
let mut transaction = TestTransaction { conn: &mut conn }; let mut transaction = TestTransaction { conn: &mut conn };
f(&mut transaction).await f(&mut transaction).await

View file

@ -12,7 +12,7 @@ LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResu
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: item does not constrain `TransactionFuture::{opaque#0}` error: item does not constrain `TransactionFuture::{opaque#0}`
--> $DIR/issue-86800.rs:37:14 --> $DIR/issue-86800.rs:36:14
| |
LL | async fn do_transaction<O>( LL | async fn do_transaction<O>(
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
@ -24,30 +24,5 @@ note: this opaque type is supposed to be constrained
LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>; LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0792]: expected generic lifetime parameter, found `'_` error: aborting due to 2 previous errors
--> $DIR/issue-86800.rs:31:5
|
LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
| --- this generic parameter must be used with a generic lifetime parameter
...
LL | f
| ^
error[E0792]: expected generic lifetime parameter, found `'_`
--> $DIR/issue-86800.rs:41:31
|
LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
| --- this generic parameter must be used with a generic lifetime parameter
...
LL | ) -> TransactionResult<O> {
| _______________________________^
LL | |
LL | | let mut conn = Connection {};
LL | | let mut transaction = TestTransaction { conn: &mut conn };
LL | | f(&mut transaction).await
LL | | }
| |_____^
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0792`.

View file

@ -0,0 +1,12 @@
error[E0792]: expected generic lifetime parameter, found `'_`
--> $DIR/as-projection-term.rs:14:19
|
LL | fn recur<'a>() -> impl Sized + 'a {
| -- this generic parameter must be used with a generic lifetime parameter
...
LL | prove_proj(|| recur());
| ^^^^^^^
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0792`.

View file

@ -0,0 +1,17 @@
//@ revisions: current next
//@[next] compile-flags: -Znext-solver
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[current] check-pass
fn prove_proj<R>(_: impl FnOnce() -> R) {}
fn recur<'a>() -> impl Sized + 'a {
// The closure has the signature `fn() -> opaque<'1>`. `prove_proj`
// requires us to prove `<closure as FnOnce<()>>::Output = opaque<'2>`.
// The old solver uses `replace_opaque_types_with_infer` during normalization
// to replace `opaque<'2>` with its hidden type. If that hidden type is still an
// inference variable at this point, we unify it with `opaque<'1>` and
// end up ignoring that defining use as the hidden type is equal to its key.
prove_proj(|| recur());
//[next]~^ ERROR expected generic lifetime parameter, found `'_`
}
fn main() {}

View file

@ -1,3 +1,12 @@
error[E0792]: expected generic type parameter, found `&str`
--> $DIR/recursive-ice-101862.rs:6:19
|
LL | pub fn ice(x: impl AsRef<str>) -> impl IntoIterator<Item = ()> {
| --------------- this generic parameter must be used with a generic type parameter
LL |
LL | vec![].append(&mut ice(x.as_ref()));
| ^^^^^^^^^^^^^^^^^^^^
warning: function cannot return without recursing warning: function cannot return without recursing
--> $DIR/recursive-ice-101862.rs:4:1 --> $DIR/recursive-ice-101862.rs:4:1
| |
@ -10,15 +19,6 @@ LL | vec![].append(&mut ice(x.as_ref()));
= help: a `loop` may express intention better if this is on purpose = help: a `loop` may express intention better if this is on purpose
= note: `#[warn(unconditional_recursion)]` on by default = note: `#[warn(unconditional_recursion)]` on by default
error[E0792]: expected generic type parameter, found `&str`
--> $DIR/recursive-ice-101862.rs:6:19
|
LL | pub fn ice(x: impl AsRef<str>) -> impl IntoIterator<Item = ()> {
| --------------- this generic parameter must be used with a generic type parameter
LL |
LL | vec![].append(&mut ice(x.as_ref()));
| ^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error; 1 warning emitted error: aborting due to 1 previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0792`. For more information about this error, try `rustc --explain E0792`.

View file

@ -1,11 +1,10 @@
use std::convert::identity; use std::convert::identity;
fn test<'a: 'a>(n: bool) -> impl Sized + 'a { fn test<'a: 'a>(n: bool) -> impl Sized + 'a {
//~^ ERROR concrete type differs from previous defining opaque type use
let true = n else { loop {} }; let true = n else { loop {} };
let _ = || { let _ = || {
let _ = identity::<&'a ()>(test(false)); let _ = identity::<&'a ()>(test(false));
//~^ ERROR expected generic lifetime parameter, found `'_` //~^ ERROR concrete type differs from previous defining opaque type use
}; };
loop {} loop {}
} }

View file

@ -1,24 +1,14 @@
error: concrete type differs from previous defining opaque type use error: concrete type differs from previous defining opaque type use
--> $DIR/early_bound.rs:6:36
|
LL | let _ = identity::<&'a ()>(test(false));
| ^^^^^^^^^^^ expected `()`, got `&()`
|
note: previous use here
--> $DIR/early_bound.rs:3:29 --> $DIR/early_bound.rs:3:29
| |
LL | fn test<'a: 'a>(n: bool) -> impl Sized + 'a { LL | fn test<'a: 'a>(n: bool) -> impl Sized + 'a {
| ^^^^^^^^^^^^^^^ expected `&()`, got `()` | ^^^^^^^^^^^^^^^
|
note: previous use here
--> $DIR/early_bound.rs:7:36
|
LL | let _ = identity::<&'a ()>(test(false));
| ^^^^^^^^^^^
error[E0792]: expected generic lifetime parameter, found `'_` error: aborting due to 1 previous error
--> $DIR/early_bound.rs:7:17
|
LL | fn test<'a: 'a>(n: bool) -> impl Sized + 'a {
| -- this generic parameter must be used with a generic lifetime parameter
...
LL | let _ = identity::<&'a ()>(test(false));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0792`.

View file

@ -6,8 +6,7 @@ fn foo<T>() -> impl Sized {
fn bar<T>(val: T) -> impl Sized { fn bar<T>(val: T) -> impl Sized {
let _: u8 = bar(0u8); let _: u8 = bar(0u8);
//~^ ERROR concrete type differs from previous defining opaque type use //~^ ERROR expected generic type parameter, found `u8`
//~| ERROR expected generic type parameter, found `u8`
val val
} }

View file

@ -1,31 +1,19 @@
error[E0792]: expected generic type parameter, found `u8` error[E0792]: expected generic type parameter, found `u8`
--> $DIR/non-defining-use.rs:4:12 --> $DIR/non-defining-use.rs:4:17
| |
LL | fn foo<T>() -> impl Sized { LL | fn foo<T>() -> impl Sized {
| - this generic parameter must be used with a generic type parameter | - this generic parameter must be used with a generic type parameter
LL | let _: () = foo::<u8>(); LL | let _: () = foo::<u8>();
| ^^ | ^^^^^^^^^^^
error: concrete type differs from previous defining opaque type use
--> $DIR/non-defining-use.rs:8:17
|
LL | let _: u8 = bar(0u8);
| ^^^^^^^^ expected `T`, got `u8`
|
note: previous use here
--> $DIR/non-defining-use.rs:7:22
|
LL | fn bar<T>(val: T) -> impl Sized {
| ^^^^^^^^^^
error[E0792]: expected generic type parameter, found `u8` error[E0792]: expected generic type parameter, found `u8`
--> $DIR/non-defining-use.rs:8:12 --> $DIR/non-defining-use.rs:8:17
| |
LL | fn bar<T>(val: T) -> impl Sized { LL | fn bar<T>(val: T) -> impl Sized {
| - this generic parameter must be used with a generic type parameter | - this generic parameter must be used with a generic type parameter
LL | let _: u8 = bar(0u8); LL | let _: u8 = bar(0u8);
| ^^ | ^^^^^^^^
error: aborting due to 3 previous errors error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0792`. For more information about this error, try `rustc --explain E0792`.

View file

@ -9,6 +9,31 @@ note: ...which requires computing type of opaque `foo::{opaque#0}`...
| |
LL | fn foo() -> impl Sized { LL | fn foo() -> impl Sized {
| ^^^^^^^^^^ | ^^^^^^^^^^
note: ...which requires borrow-checking `foo`...
--> $DIR/in-defining-scope.rs:6:1
|
LL | fn foo() -> impl Sized {
| ^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires promoting constants in MIR for `foo`...
--> $DIR/in-defining-scope.rs:6:1
|
LL | fn foo() -> impl Sized {
| ^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires checking if `foo` contains FFI-unwind calls...
--> $DIR/in-defining-scope.rs:6:1
|
LL | fn foo() -> impl Sized {
| ^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires building MIR for `foo`...
--> $DIR/in-defining-scope.rs:6:1
|
LL | fn foo() -> impl Sized {
| ^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires match-checking `foo`...
--> $DIR/in-defining-scope.rs:6:1
|
LL | fn foo() -> impl Sized {
| ^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires type-checking `foo`... note: ...which requires type-checking `foo`...
--> $DIR/in-defining-scope.rs:6:1 --> $DIR/in-defining-scope.rs:6:1
| |

View file

@ -1,18 +1,5 @@
error: item does not constrain `A::{opaque#0}`
--> $DIR/two_tait_defining_each_other2.rs:12:4
|
LL | fn muh(x: A) -> B {
| ^^^
|
= note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
note: this opaque type is supposed to be constrained
--> $DIR/two_tait_defining_each_other2.rs:6:10
|
LL | type A = impl Foo;
| ^^^^^^^^
error: opaque type's hidden type cannot be another opaque type from the same scope error: opaque type's hidden type cannot be another opaque type from the same scope
--> $DIR/two_tait_defining_each_other2.rs:15:5 --> $DIR/two_tait_defining_each_other2.rs:14:5
| |
LL | x // B's hidden type is A (opaquely) LL | x // B's hidden type is A (opaquely)
| ^ one of the two opaque types used here has to be outside its defining scope | ^ one of the two opaque types used here has to be outside its defining scope
@ -28,5 +15,5 @@ note: opaque type being used as hidden type
LL | type A = impl Foo; LL | type A = impl Foo;
| ^^^^^^^^ | ^^^^^^^^
error: aborting due to 2 previous errors error: aborting due to 1 previous error

View file

@ -10,8 +10,7 @@ trait Foo {}
#[define_opaque(A, B)] #[define_opaque(A, B)]
fn muh(x: A) -> B { fn muh(x: A) -> B {
//[current]~^ ERROR: item does not constrain `A::{opaque#0}` //[next]~^ ERROR: cannot satisfy `_ == A`
//[next]~^^ ERROR: cannot satisfy `_ == A`
x // B's hidden type is A (opaquely) x // B's hidden type is A (opaquely)
//[current]~^ ERROR opaque type's hidden type cannot be another opaque type //[current]~^ ERROR opaque type's hidden type cannot be another opaque type
} }

View file

@ -1,5 +1,8 @@
//@ known-bug: #132335 // Regression test for #132335. This previously ICE'd due to ambiguity
// in MIR typeck.
//@ compile-flags: -Znext-solver=globally --crate-type lib --edition=2018 //@ compile-flags: -Znext-solver=globally --crate-type lib --edition=2018
//@ check-pass
use core::future::Future; use core::future::Future;
use core::pin::Pin; use core::pin::Pin;

View file

@ -1,34 +1,54 @@
error: unconstrained opaque type error: item does not constrain `ex1::Tait1::{opaque#0}`
--> $DIR/no-define-in-wf-check.rs:21:8
|
LL | fn foo(x: Tait1) -> impl Sized {
| ^^^
|
= note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
note: this opaque type is supposed to be constrained
--> $DIR/no-define-in-wf-check.rs:19:18 --> $DIR/no-define-in-wf-check.rs:19:18
| |
LL | type Tait1 = impl Sized; LL | type Tait1 = impl Sized;
| ^^^^^^^^^^ | ^^^^^^^^^^
|
= note: `Tait1` must be used in combination with a concrete type within the same crate
error: unconstrained opaque type error: item does not constrain `ex2::Tait1::{opaque#0}`
--> $DIR/no-define-in-wf-check.rs:31:8
|
LL | fn foo(x: Tait1) -> Tait2 {
| ^^^
|
= note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
note: this opaque type is supposed to be constrained
--> $DIR/no-define-in-wf-check.rs:28:18 --> $DIR/no-define-in-wf-check.rs:28:18
| |
LL | type Tait1 = impl Sized; LL | type Tait1 = impl Sized;
| ^^^^^^^^^^ | ^^^^^^^^^^
|
= note: `Tait1` must be used in combination with a concrete type within the same crate
error: unconstrained opaque type error: item does not constrain `ex3::Tait1::{opaque#0}`
--> $DIR/no-define-in-wf-check.rs:43:8
|
LL | fn foo(x: Tait1) -> Tait2 {
| ^^^
|
= note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
note: this opaque type is supposed to be constrained
--> $DIR/no-define-in-wf-check.rs:38:18 --> $DIR/no-define-in-wf-check.rs:38:18
| |
LL | type Tait1 = impl Sized; LL | type Tait1 = impl Sized;
| ^^^^^^^^^^ | ^^^^^^^^^^
|
= note: `Tait1` must be used in combination with a concrete type within the same crate
error: unconstrained opaque type error: item does not constrain `ex4::Tait1::{opaque#0}`
--> $DIR/no-define-in-wf-check.rs:64:8
|
LL | fn foo(x: Tait1) -> Tait2 {
| ^^^
|
= note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
note: this opaque type is supposed to be constrained
--> $DIR/no-define-in-wf-check.rs:50:18 --> $DIR/no-define-in-wf-check.rs:50:18
| |
LL | type Tait1 = impl Sized; LL | type Tait1 = impl Sized;
| ^^^^^^^^^^ | ^^^^^^^^^^
|
= note: `Tait1` must be used in combination with a concrete type within the same crate
error: aborting due to 4 previous errors error: aborting due to 4 previous errors

View file

@ -17,38 +17,37 @@ mod ex0 {
} }
mod ex1 { mod ex1 {
type Tait1 = impl Sized; type Tait1 = impl Sized;
//[current]~^ ERROR unconstrained opaque type
#[define_opaque(Tait1)] #[define_opaque(Tait1)]
fn foo(x: Tait1) -> impl Sized { fn foo(x: Tait1) -> impl Sized {
//[current]~^ ERROR item does not constrain `ex1::Tait1::{opaque#0}`
let () = x; let () = x;
} }
} }
mod ex2 { mod ex2 {
type Tait1 = impl Sized; type Tait1 = impl Sized;
//[current]~^ ERROR unconstrained opaque type
type Tait2 = impl Sized; type Tait2 = impl Sized;
#[define_opaque(Tait1, Tait2)] #[define_opaque(Tait1, Tait2)]
fn foo(x: Tait1) -> Tait2 { fn foo(x: Tait1) -> Tait2 {
//[current]~^ ERROR item does not constrain `ex2::Tait1::{opaque#0}`
let () = x; let () = x;
} }
} }
mod ex3 { mod ex3 {
type Tait1 = impl Sized; type Tait1 = impl Sized;
//[current]~^ ERROR unconstrained opaque type
trait Something<T> {} trait Something<T> {}
impl<T, U> Something<U> for T {} impl<T, U> Something<U> for T {}
type Tait2 = impl Something<Tait1>; type Tait2 = impl Something<Tait1>;
#[define_opaque(Tait1, Tait2)] #[define_opaque(Tait1, Tait2)]
fn foo(x: Tait1) -> Tait2 { fn foo(x: Tait1) -> Tait2 {
//[current]~^ ERROR item does not constrain `ex3::Tait1::{opaque#0}`
let () = x; let () = x;
} }
} }
mod ex4 { mod ex4 {
type Tait1 = impl Sized; type Tait1 = impl Sized;
//[current]~^ ERROR unconstrained opaque type
trait Trait<U> { trait Trait<U> {
type Assoc; type Assoc;
} }
@ -63,6 +62,7 @@ mod ex4 {
type Tait2 = impl Trait<(), Assoc = impl Trait<Tait1>>; type Tait2 = impl Trait<(), Assoc = impl Trait<Tait1>>;
#[define_opaque(Tait1, Tait2)] #[define_opaque(Tait1, Tait2)]
fn foo(x: Tait1) -> Tait2 { fn foo(x: Tait1) -> Tait2 {
//[current]~^ ERROR item does not constrain `ex4::Tait1::{opaque#0}`
let () = x; let () = x;
} }
} }

View file

@ -0,0 +1,11 @@
// Regression test for #137751. This previously ICE'd as
// we did not provide the hidden type of the opaque inside
// of the async block. This caused borrowck of the recursive
// call to ICE.
//@ compile-flags: --edition=2021
//@ check-pass
async fn test() {
Box::pin(test()).await;
}
fn main() {}

View file

@ -12,7 +12,6 @@ pub enum UninhabitedVariants {
#[define_opaque(Alias)] #[define_opaque(Alias)]
fn uwu(x: UninhabitedVariants) { fn uwu(x: UninhabitedVariants) {
//~^ ERROR item does not constrain
match x {} match x {}
//~^ ERROR non-exhaustive patterns //~^ ERROR non-exhaustive patterns
} }

View file

@ -26,21 +26,8 @@ help: add missing generic argument
LL | Tuple(Alias<U>), LL | Tuple(Alias<U>),
| +++ | +++
error: item does not constrain `Alias::{opaque#0}`
--> $DIR/bad-tait-no-substs.rs:14:4
|
LL | fn uwu(x: UninhabitedVariants) {
| ^^^
|
= note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
note: this opaque type is supposed to be constrained
--> $DIR/bad-tait-no-substs.rs:5:21
|
LL | type Alias<'a, U> = impl Trait<U>;
| ^^^^^^^^^^^^^
error[E0004]: non-exhaustive patterns: `UninhabitedVariants::Tuple(_)` not covered error[E0004]: non-exhaustive patterns: `UninhabitedVariants::Tuple(_)` not covered
--> $DIR/bad-tait-no-substs.rs:16:11 --> $DIR/bad-tait-no-substs.rs:15:11
| |
LL | match x {} LL | match x {}
| ^ pattern `UninhabitedVariants::Tuple(_)` not covered | ^ pattern `UninhabitedVariants::Tuple(_)` not covered
@ -60,7 +47,7 @@ LL + UninhabitedVariants::Tuple(_) => todo!(),
LL ~ } LL ~ }
| |
error: aborting due to 4 previous errors error: aborting due to 3 previous errors
Some errors have detailed explanations: E0004, E0106, E0107. Some errors have detailed explanations: E0004, E0106, E0107.
For more information about an error, try `rustc --explain E0004`. For more information about an error, try `rustc --explain E0004`.

View file

@ -14,6 +14,6 @@ impl<W> Trait<W> for () {}
#[define_opaque(Foo)] #[define_opaque(Foo)]
fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> { fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
()
//~^ ERROR expected generic type parameter, found `<T as TraitWithAssoc>::Assoc` //~^ ERROR expected generic type parameter, found `<T as TraitWithAssoc>::Assoc`
()
} }

View file

@ -1,11 +1,11 @@
error[E0792]: expected generic type parameter, found `<T as TraitWithAssoc>::Assoc` error[E0792]: expected generic type parameter, found `<T as TraitWithAssoc>::Assoc`
--> $DIR/bound_reduction2.rs:17:5 --> $DIR/bound_reduction2.rs:16:46
| |
LL | type Foo<V> = impl Trait<V>; LL | type Foo<V> = impl Trait<V>;
| - this generic parameter must be used with a generic type parameter | - this generic parameter must be used with a generic type parameter
... ...
LL | () LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
| ^^ | ^^^^^^^^^^^^^
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -9,7 +9,7 @@ fn get_one<'a>(a: *mut &'a str) -> Opaque<'a> {
#[define_opaque(Opaque)] #[define_opaque(Opaque)]
fn get_iter<'a>() -> impl IntoIterator<Item = Opaque<'a>> { fn get_iter<'a>() -> impl IntoIterator<Item = Opaque<'a>> {
//~^ ERROR: item does not constrain //~^ ERROR item does not constrain `Opaque::{opaque#0}`
None::<Opaque<'static>> None::<Opaque<'static>>
} }

View file

@ -12,6 +12,6 @@ fn foo() -> Foo {
#[define_opaque(Foo)] #[define_opaque(Foo)]
fn bar() -> Foo { fn bar() -> Foo {
//~^ ERROR concrete type differs
42i32 42i32
//~^ ERROR concrete type differs from previous
} }

View file

@ -1,14 +1,14 @@
error: concrete type differs from previous defining opaque type use error: concrete type differs from previous defining opaque type use
--> $DIR/different_defining_uses.rs:15:5 --> $DIR/different_defining_uses.rs:14:13
| |
LL | 42i32 LL | fn bar() -> Foo {
| ^^^^^ expected `&'static str`, got `i32` | ^^^ expected `&str`, got `i32`
| |
note: previous use here note: previous use here
--> $DIR/different_defining_uses.rs:10:5 --> $DIR/different_defining_uses.rs:9:13
| |
LL | "" LL | fn foo() -> Foo {
| ^^ | ^^^
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -12,7 +12,6 @@ fn foo<'a, 'b>() -> Tait<'a> {
} }
let x: Tait<'a> = (); let x: Tait<'a> = ();
x x
//~^ ERROR concrete type differs from previous defining opaque type use
} }
fn main() {} fn main() {}

View file

@ -1,15 +1,3 @@
error: concrete type differs from previous defining opaque type use
--> $DIR/different_defining_uses_never_type-2.rs:14:5
|
LL | x
| ^ expected `i32`, got `()`
|
note: previous use here
--> $DIR/different_defining_uses_never_type-2.rs:9:31
|
LL | let y: Tait<'b> = 1i32;
| ^^^^
error: concrete type differs from previous defining opaque type use error: concrete type differs from previous defining opaque type use
--> $DIR/different_defining_uses_never_type-2.rs:9:31 --> $DIR/different_defining_uses_never_type-2.rs:9:31
| |
@ -17,10 +5,10 @@ LL | let y: Tait<'b> = 1i32;
| ^^^^ expected `()`, got `i32` | ^^^^ expected `()`, got `i32`
| |
note: previous use here note: previous use here
--> $DIR/different_defining_uses_never_type-2.rs:8:14 --> $DIR/different_defining_uses_never_type-2.rs:14:5
| |
LL | if { return } { LL | x
| ^^^^^^ | ^
error: aborting due to 2 previous errors error: aborting due to 1 previous error

View file

@ -5,10 +5,10 @@ LL | let y: Tait<U> = 1i32;
| ^^^^ expected `()`, got `i32` | ^^^^ expected `()`, got `i32`
| |
note: previous use here note: previous use here
--> $DIR/different_defining_uses_never_type-3.rs:13:22 --> $DIR/different_defining_uses_never_type-3.rs:14:5
| |
LL | let x: Tait<T> = (); LL | x
| ^^ | ^
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -2,13 +2,13 @@ error: concrete type differs from previous defining opaque type use
--> $DIR/different_defining_uses_never_type.rs:14:13 --> $DIR/different_defining_uses_never_type.rs:14:13
| |
LL | fn bar() -> Foo { LL | fn bar() -> Foo {
| ^^^ expected `&'static str`, got `()` | ^^^ expected `&str`, got `()`
| |
note: previous use here note: previous use here
--> $DIR/different_defining_uses_never_type.rs:10:5 --> $DIR/different_defining_uses_never_type.rs:9:13
| |
LL | "" LL | fn foo() -> Foo {
| ^^ | ^^^
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -5,10 +5,10 @@ LL | fn two() -> Tait { Two::<()>(todo!()) }
| ^^^^ expected `One`, got `Two<()>` | ^^^^ expected `One`, got `Two<()>`
| |
note: previous use here note: previous use here
--> $DIR/different_defining_uses_never_type3.rs:7:20 --> $DIR/different_defining_uses_never_type3.rs:7:13
| |
LL | fn one() -> Tait { One } LL | fn one() -> Tait { One }
| ^^^ | ^^^^
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -31,7 +31,6 @@ impl<F: for<'a> Fn(&'a ()) -> StateWidget<'a>> Widget<()> for StatefulWidget<F>
fn new_stateful_widget<F: for<'a> Fn(&'a ()) -> StateWidget<'a>>(build: F) -> impl Widget<()> { fn new_stateful_widget<F: for<'a> Fn(&'a ()) -> StateWidget<'a>>(build: F) -> impl Widget<()> {
//~^ ERROR item does not constrain //~^ ERROR item does not constrain
StatefulWidget(build) StatefulWidget(build)
//~^ ERROR expected generic lifetime parameter, found `'a`
} }
fn main() { fn main() {

View file

@ -24,17 +24,8 @@ note: this opaque type is supposed to be constrained
LL | type StateWidget<'a> = impl Widget<&'a ()>; LL | type StateWidget<'a> = impl Widget<&'a ()>;
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
error[E0792]: expected generic lifetime parameter, found `'a`
--> $DIR/failed-to-normalize-ice-99945.rs:33:5
|
LL | type StateWidget<'a> = impl Widget<&'a ()>;
| -- this generic parameter must be used with a generic lifetime parameter
...
LL | StatefulWidget(build)
| ^^^^^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/failed-to-normalize-ice-99945.rs:38:29 --> $DIR/failed-to-normalize-ice-99945.rs:37:29
| |
LL | type StateWidget<'a> = impl Widget<&'a ()>; LL | type StateWidget<'a> = impl Widget<&'a ()>;
| ------------------- the expected opaque type | ------------------- the expected opaque type
@ -45,7 +36,6 @@ LL | new_stateful_widget(|_| ()).make_state();
= note: expected opaque type `StateWidget<'_>` = note: expected opaque type `StateWidget<'_>`
found unit type `()` found unit type `()`
error: aborting due to 4 previous errors error: aborting due to 3 previous errors
Some errors have detailed explanations: E0308, E0792. For more information about this error, try `rustc --explain E0308`.
For more information about an error, try `rustc --explain E0308`.

View file

@ -11,6 +11,6 @@ fn my_iter<T>(t: T) -> MyIter<T> {
#[define_opaque(MyIter)] #[define_opaque(MyIter)]
fn my_iter2<T>(t: T) -> MyIter<T> { fn my_iter2<T>(t: T) -> MyIter<T> {
Some(t).into_iter()
//~^ ERROR concrete type differs from previous //~^ ERROR concrete type differs from previous
Some(t).into_iter()
} }

View file

@ -1,14 +1,14 @@
error: concrete type differs from previous defining opaque type use error: concrete type differs from previous defining opaque type use
--> $DIR/generic_different_defining_uses.rs:14:5 --> $DIR/generic_different_defining_uses.rs:13:25
| |
LL | Some(t).into_iter() LL | fn my_iter2<T>(t: T) -> MyIter<T> {
| ^^^^^^^^^^^^^^^^^^^ expected `std::iter::Once<T>`, got `std::option::IntoIter<T>` | ^^^^^^^^^ expected `std::iter::Once<T>`, got `std::option::IntoIter<T>`
| |
note: previous use here note: previous use here
--> $DIR/generic_different_defining_uses.rs:9:5 --> $DIR/generic_different_defining_uses.rs:8:24
| |
LL | std::iter::once(t) LL | fn my_iter<T>(t: T) -> MyIter<T> {
| ^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -20,8 +20,8 @@ type TwoConsts<const X: usize, const Y: usize> = impl Debug;
#[define_opaque(TwoTys)] #[define_opaque(TwoTys)]
fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> { fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
t
//~^ ERROR non-defining opaque type use in defining scope //~^ ERROR non-defining opaque type use in defining scope
t
} }
#[define_opaque(TwoLifetimes)] #[define_opaque(TwoLifetimes)]
@ -32,6 +32,6 @@ fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> {
#[define_opaque(TwoConsts)] #[define_opaque(TwoConsts)]
fn one_const<const N: usize>(t: *mut [u8; N]) -> TwoConsts<N, N> { fn one_const<const N: usize>(t: *mut [u8; N]) -> TwoConsts<N, N> {
t
//~^ ERROR non-defining opaque type use in defining scope //~^ ERROR non-defining opaque type use in defining scope
t
} }

View file

@ -1,8 +1,8 @@
error: non-defining opaque type use in defining scope error: non-defining opaque type use in defining scope
--> $DIR/generic_duplicate_param_use.rs:23:5 --> $DIR/generic_duplicate_param_use.rs:22:30
| |
LL | t LL | fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
| ^ | ^^^^^^^^^^^^
| |
note: type used multiple times note: type used multiple times
--> $DIR/generic_duplicate_param_use.rs:15:13 --> $DIR/generic_duplicate_param_use.rs:15:13
@ -23,10 +23,10 @@ LL | type TwoLifetimes<'a, 'b> = impl Debug;
| ^^ ^^ | ^^ ^^
error: non-defining opaque type use in defining scope error: non-defining opaque type use in defining scope
--> $DIR/generic_duplicate_param_use.rs:35:5 --> $DIR/generic_duplicate_param_use.rs:34:50
| |
LL | t LL | fn one_const<const N: usize>(t: *mut [u8; N]) -> TwoConsts<N, N> {
| ^ | ^^^^^^^^^^^^^^^
| |
note: constant used multiple times note: constant used multiple times
--> $DIR/generic_duplicate_param_use.rs:19:16 --> $DIR/generic_duplicate_param_use.rs:19:16

View file

@ -14,6 +14,6 @@ fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
#[define_opaque(Two)] #[define_opaque(Two)]
fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> { fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
u
//~^ ERROR concrete type differs //~^ ERROR concrete type differs
u
} }

View file

@ -1,14 +1,14 @@
error: concrete type differs from previous defining opaque type use error: concrete type differs from previous defining opaque type use
--> $DIR/generic_duplicate_param_use3.rs:17:5 --> $DIR/generic_duplicate_param_use3.rs:16:38
| |
LL | u LL | fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
| ^ expected `T`, got `U` | ^^^^^^^^^ expected `T`, got `U`
| |
note: previous use here note: previous use here
--> $DIR/generic_duplicate_param_use3.rs:12:5 --> $DIR/generic_duplicate_param_use3.rs:11:36
| |
LL | t LL | fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
| ^ | ^^^^^^^^^
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -14,6 +14,6 @@ fn two<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
#[define_opaque(Two)] #[define_opaque(Two)]
fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> { fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
(u, t)
//~^ ERROR concrete type differs //~^ ERROR concrete type differs
(u, t)
} }

View file

@ -1,14 +1,14 @@
error: concrete type differs from previous defining opaque type use error: concrete type differs from previous defining opaque type use
--> $DIR/generic_duplicate_param_use5.rs:17:5 --> $DIR/generic_duplicate_param_use5.rs:16:45
| |
LL | (u, t) LL | fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
| ^^^^^^ expected `(T, U)`, got `(U, T)` | ^^^^^^^^^ expected `(T, U)`, got `(U, T)`
| |
note: previous use here note: previous use here
--> $DIR/generic_duplicate_param_use5.rs:12:5 --> $DIR/generic_duplicate_param_use5.rs:11:43
| |
LL | (t, u) LL | fn two<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
| ^^^^^^ | ^^^^^^^^^
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -14,6 +14,6 @@ fn two<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
#[define_opaque(Two)] #[define_opaque(Two)]
fn three<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> { fn three<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
(u, t)
//~^ ERROR concrete type differs //~^ ERROR concrete type differs
(u, t)
} }

View file

@ -1,14 +1,14 @@
error: concrete type differs from previous defining opaque type use error: concrete type differs from previous defining opaque type use
--> $DIR/generic_duplicate_param_use6.rs:17:5 --> $DIR/generic_duplicate_param_use6.rs:16:52
| |
LL | (u, t) LL | fn three<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
| ^^^^^^ expected `(T, T)`, got `(U, T)` | ^^^^^^^^^ expected `(T, T)`, got `(U, T)`
| |
note: previous use here note: previous use here
--> $DIR/generic_duplicate_param_use6.rs:12:5 --> $DIR/generic_duplicate_param_use6.rs:11:50
| |
LL | (t, t) LL | fn two<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
| ^^^^^^ | ^^^^^^^^^
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -13,6 +13,6 @@ fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> {
#[define_opaque(Two)] #[define_opaque(Two)]
fn three<T: Debug, U: Debug>(_: T, u: U) -> Two<T, U> { fn three<T: Debug, U: Debug>(_: T, u: U) -> Two<T, U> {
(u, 4u32)
//~^ concrete type differs //~^ concrete type differs
(u, 4u32)
} }

View file

@ -1,14 +1,14 @@
error: concrete type differs from previous defining opaque type use error: concrete type differs from previous defining opaque type use
--> $DIR/generic_duplicate_param_use8.rs:16:5 --> $DIR/generic_duplicate_param_use8.rs:15:45
| |
LL | (u, 4u32) LL | fn three<T: Debug, U: Debug>(_: T, u: U) -> Two<T, U> {
| ^^^^^^^^^ expected `(T, u32)`, got `(U, u32)` | ^^^^^^^^^ expected `(T, u32)`, got `(U, u32)`
| |
note: previous use here note: previous use here
--> $DIR/generic_duplicate_param_use8.rs:11:5 --> $DIR/generic_duplicate_param_use8.rs:10:43
| |
LL | (t, 4u32) LL | fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> {
| ^^^^^^^^^ | ^^^^^^^^^
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -18,6 +18,6 @@ fn two<T: Debug + Foo, U: Debug>(t: T, u: U) -> Two<T, U> {
#[define_opaque(Two)] #[define_opaque(Two)]
fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> { fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
(t, u, 42)
//~^ ERROR concrete type differs //~^ ERROR concrete type differs
(t, u, 42)
} }

View file

@ -1,14 +1,14 @@
error: concrete type differs from previous defining opaque type use error: concrete type differs from previous defining opaque type use
--> $DIR/generic_duplicate_param_use9.rs:21:5 --> $DIR/generic_duplicate_param_use9.rs:20:45
| |
LL | (t, u, 42) LL | fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
| ^^^^^^^^^^ expected `(A, B, <A as Foo>::Bar)`, got `(A, B, i32)` | ^^^^^^^^^ expected `(A, B, <A as Foo>::Bar)`, got `(A, B, i32)`
| |
note: previous use here note: previous use here
--> $DIR/generic_duplicate_param_use9.rs:16:5 --> $DIR/generic_duplicate_param_use9.rs:15:49
| |
LL | (t, u, T::BAR) LL | fn two<T: Debug + Foo, U: Debug>(t: T, u: U) -> Two<T, U> {
| ^^^^^^^^^^^^^^ | ^^^^^^^^^
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -14,8 +14,8 @@ type OneConst<const X: usize> = impl Debug;
#[define_opaque(OneTy)] #[define_opaque(OneTy)]
fn concrete_ty() -> OneTy<u32> { fn concrete_ty() -> OneTy<u32> {
5u32
//~^ ERROR: expected generic type parameter, found `u32` //~^ ERROR: expected generic type parameter, found `u32`
5u32
} }
#[define_opaque(OneLifetime)] #[define_opaque(OneLifetime)]
@ -26,6 +26,6 @@ fn concrete_lifetime() -> OneLifetime<'static> {
#[define_opaque(OneConst)] #[define_opaque(OneConst)]
fn concrete_const() -> OneConst<{ 123 }> { fn concrete_const() -> OneConst<{ 123 }> {
7u32
//~^ ERROR: expected generic constant parameter, found `123` //~^ ERROR: expected generic constant parameter, found `123`
7u32
} }

View file

@ -1,11 +1,11 @@
error[E0792]: expected generic type parameter, found `u32` error[E0792]: expected generic type parameter, found `u32`
--> $DIR/generic_nondefining_use.rs:17:5 --> $DIR/generic_nondefining_use.rs:16:21
| |
LL | type OneTy<T> = impl Debug; LL | type OneTy<T> = impl Debug;
| - this generic parameter must be used with a generic type parameter | - this generic parameter must be used with a generic type parameter
... ...
LL | 5u32 LL | fn concrete_ty() -> OneTy<u32> {
| ^^^^ | ^^^^^^^^^^
error[E0792]: expected generic lifetime parameter, found `'static` error[E0792]: expected generic lifetime parameter, found `'static`
--> $DIR/generic_nondefining_use.rs:23:5 --> $DIR/generic_nondefining_use.rs:23:5
@ -17,13 +17,13 @@ LL | 6u32
| ^^^^ | ^^^^
error[E0792]: expected generic constant parameter, found `123` error[E0792]: expected generic constant parameter, found `123`
--> $DIR/generic_nondefining_use.rs:29:5 --> $DIR/generic_nondefining_use.rs:28:24
| |
LL | type OneConst<const X: usize> = impl Debug; LL | type OneConst<const X: usize> = impl Debug;
| -------------- this generic parameter must be used with a generic constant parameter | -------------- this generic parameter must be used with a generic constant parameter
... ...
LL | 7u32 LL | fn concrete_const() -> OneConst<{ 123 }> {
| ^^^^ | ^^^^^^^^^^^^^^^^^
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View file

@ -7,6 +7,6 @@ type WrongGeneric<T: 'static> = impl 'static;
#[define_opaque(WrongGeneric)] #[define_opaque(WrongGeneric)]
fn wrong_generic<U: 'static, V: 'static>(_: U, v: V) -> WrongGeneric<U> { fn wrong_generic<U: 'static, V: 'static>(_: U, v: V) -> WrongGeneric<U> {
v
//~^ ERROR type parameter `V` is part of concrete type but not used in parameter list //~^ ERROR type parameter `V` is part of concrete type but not used in parameter list
v
} }

View file

@ -5,10 +5,10 @@ LL | type WrongGeneric<T: 'static> = impl 'static;
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^
error: type parameter `V` is part of concrete type but not used in parameter list for the `impl Trait` type alias error: type parameter `V` is part of concrete type but not used in parameter list for the `impl Trait` type alias
--> $DIR/generic_not_used.rs:10:5 --> $DIR/generic_not_used.rs:9:57
| |
LL | v LL | fn wrong_generic<U: 'static, V: 'static>(_: U, v: V) -> WrongGeneric<U> {
| ^ | ^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

Some files were not shown because too many files have changed in this diff Show more