add TypingMode::Borrowck
This commit is contained in:
parent
990201cb78
commit
509a144eed
131 changed files with 888 additions and 747 deletions
|
@ -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> {
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:?}")
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
///
|
///
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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),
|
||||||
},
|
},
|
||||||
|
|
|
@ -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),
|
||||||
},
|
},
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)"),
|
||||||
|
|
|
@ -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(_)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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 => {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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),
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() {}
|
|
|
@ -1,6 +0,0 @@
|
||||||
//@ known-bug: #137751
|
|
||||||
//@ compile-flags: --edition=2021 -Znext-solver=globally
|
|
||||||
async fn test() {
|
|
||||||
Box::pin(test()).await;
|
|
||||||
}
|
|
||||||
fn main() {}
|
|
|
@ -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
|
||||||
|
|
|
@ -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!())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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!())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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`.
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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`.
|
||||||
|
|
|
@ -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 {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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`
|
||||||
|
|
||||||
|
|
|
@ -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 {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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`.
|
||||||
|
|
|
@ -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
|
||||||
|
|| ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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`.
|
||||||
|
|
|
@ -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`
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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`.
|
||||||
|
|
17
tests/ui/impl-trait/issues/fuzzer-ice-issue-112201.rs
Normal file
17
tests/ui/impl-trait/issues/fuzzer-ice-issue-112201.rs
Normal 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() {}
|
18
tests/ui/impl-trait/issues/fuzzer-ice-issue-112201.stderr
Normal file
18
tests/ui/impl-trait/issues/fuzzer-ice-issue-112201.stderr
Normal 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`.
|
|
@ -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
|
||||||
|
|
|
@ -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`.
|
|
||||||
|
|
|
@ -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`.
|
17
tests/ui/impl-trait/non-defining-uses/as-projection-term.rs
Normal file
17
tests/ui/impl-trait/non-defining-uses/as-projection-term.rs
Normal 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() {}
|
|
@ -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`.
|
||||||
|
|
|
@ -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 {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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`.
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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`.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() {}
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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`.
|
||||||
|
|
|
@ -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`
|
||||||
|
()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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>>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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() {}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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`.
|
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue