Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 46 additions & 5 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ use tracing::instrument;
use super::errors::{InvalidAbi, InvalidAbiSuggestion, TupleStructWithDefault, UnionWithDefault};
use super::stability::{enabled_names, gate_unstable_abi};
use super::{
AstOwner, FnDeclKind, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode,
RelaxedBoundForbiddenReason, RelaxedBoundPolicy, ResolverAstLoweringExt,
AstOwner, FnDeclKind, GenericArgsMode, ImplTraitContext, ImplTraitPosition, LoweringContext,
ParamMode, RelaxedBoundForbiddenReason, RelaxedBoundPolicy, ResolverAstLoweringExt,
};

/// Wraps either IndexVec (during `hir_crate`), which acts like a primary
Expand Down Expand Up @@ -536,14 +536,14 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
constness,
is_auto,
safety,
// FIXME(impl_restrictions): lower to HIR
impl_restriction: _,
impl_restriction,
ident,
generics,
bounds,
items,
}) => {
let constness = self.lower_constness(*constness);
let impl_restriction = self.lower_impl_restriction(impl_restriction);
let ident = self.lower_ident(*ident);
let (generics, (safety, items, bounds)) = self.lower_generics(
generics,
Expand All @@ -562,7 +562,16 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
(safety, items, bounds)
},
);
hir::ItemKind::Trait(constness, *is_auto, safety, ident, generics, bounds, items)
hir::ItemKind::Trait(
constness,
*is_auto,
safety,
impl_restriction,
ident,
generics,
bounds,
items,
)
}
ItemKind::TraitAlias(box TraitAlias { constness, ident, generics, bounds }) => {
let constness = self.lower_constness(*constness);
Expand Down Expand Up @@ -1827,6 +1836,38 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
}
}

pub(super) fn lower_impl_restriction(
&mut self,
r: &ImplRestriction,
) -> &'hir hir::ImplRestriction<'hir> {
let kind = match &r.kind {
RestrictionKind::Unrestricted => hir::RestrictionKind::Unrestricted,
RestrictionKind::Restricted { path, id, shorthand: _ } => {
let res = self.resolver.get_partial_res(*id);
if let Some(did) = res.and_then(|res| res.expect_full_res().opt_def_id()) {
hir::RestrictionKind::Restricted(self.arena.alloc(hir::Path {
res: did,
segments: self.arena.alloc_from_iter(path.segments.iter().map(|segment| {
self.lower_path_segment(
path.span,
segment,
ParamMode::Explicit,
GenericArgsMode::Err,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
)
})),
span: self.lower_span(path.span),
}))
} else {
self.dcx().span_delayed_bug(path.span, "should have errored in resolve");
hir::RestrictionKind::Unrestricted
}
}
};
self.arena.alloc(hir::ImplRestriction { kind, span: self.lower_span(r.span) })
}

/// Return the pair of the lowered `generics` as `hir::Generics` and the evaluation of `f` with
/// the carried impl trait definitions and bounds.
#[instrument(level = "debug", skip(self, f))]
Expand Down
24 changes: 20 additions & 4 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4326,13 +4326,14 @@ impl<'hir> Item<'hir> {
Constness,
IsAuto,
Safety,
&'hir ImplRestriction<'hir>,
Ident,
&'hir Generics<'hir>,
GenericBounds<'hir>,
&'hir [TraitItemId]
),
ItemKind::Trait(constness, is_auto, safety, ident, generics, bounds, items),
(*constness, *is_auto, *safety, *ident, generics, bounds, items);
ItemKind::Trait(constness, is_auto, safety, impl_restriction, ident, generics, bounds, items),
(*constness, *is_auto, *safety, impl_restriction, *ident, generics, bounds, items);

expect_trait_alias, (Constness, Ident, &'hir Generics<'hir>, GenericBounds<'hir>),
ItemKind::TraitAlias(constness, ident, generics, bounds), (*constness, *ident, generics, bounds);
Expand Down Expand Up @@ -4401,6 +4402,20 @@ impl fmt::Display for Constness {
}
}

#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub struct ImplRestriction<'hir> {
pub kind: RestrictionKind<'hir>,
pub span: Span,
}

#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub enum RestrictionKind<'hir> {
/// The restriction does not affect the item.
Unrestricted,
/// The restriction only applies outside of this path.
Restricted(&'hir Path<'hir, DefId>),
}

/// The actual safety specified in syntax. We may treat
/// its safety different within the type system to create a
/// "sound by default" system that needs checking this enum
Expand Down Expand Up @@ -4513,6 +4528,7 @@ pub enum ItemKind<'hir> {
Constness,
IsAuto,
Safety,
&'hir ImplRestriction<'hir>,
Ident,
&'hir Generics<'hir>,
GenericBounds<'hir>,
Expand Down Expand Up @@ -4563,7 +4579,7 @@ impl ItemKind<'_> {
| ItemKind::Enum(ident, ..)
| ItemKind::Struct(ident, ..)
| ItemKind::Union(ident, ..)
| ItemKind::Trait(_, _, _, ident, ..)
| ItemKind::Trait(_, _, _, _, ident, ..)
| ItemKind::TraitAlias(_, ident, ..) => Some(ident),

ItemKind::Use(_, UseKind::Glob | UseKind::ListStem)
Expand All @@ -4581,7 +4597,7 @@ impl ItemKind<'_> {
| ItemKind::Enum(_, generics, _)
| ItemKind::Struct(_, generics, _)
| ItemKind::Union(_, generics, _)
| ItemKind::Trait(_, _, _, _, generics, _, _)
| ItemKind::Trait(_, _, _, _, _, generics, _, _)
| ItemKind::TraitAlias(_, _, generics, _)
| ItemKind::Impl(Impl { generics, .. }) => generics,
_ => return None,
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -622,11 +622,15 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
_constness,
_is_auto,
_safety,
ref impl_restriction,
ident,
ref generics,
bounds,
trait_item_refs,
) => {
if let RestrictionKind::Restricted(path) = &impl_restriction.kind {
walk_list!(visitor, visit_path_segment, path.segments);
}
try_visit!(visitor.visit_ident(ident));
try_visit!(visitor.visit_generics(generics));
walk_list!(visitor, visit_param_bound, bounds);
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_hir_analysis/src/coherence/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,14 @@ fn enforce_trait_manually_implementable(
return Err(tcx.dcx().emit_err(errors::SpecializationTrait { span: impl_header_span }));
}
}

if !trait_def.impl_restriction.is_allowed_in(impl_def_id.to_def_id(), tcx) {
return Err(tcx.dcx().emit_err(errors::ImplOfRestrictedTrait {
impl_span: impl_header_span,
restriction_span: trait_def.impl_restriction.expect_span(),
restriction_path: trait_def.impl_restriction.restriction_path(tcx),
}));
}
Ok(())
}

Expand Down
25 changes: 20 additions & 5 deletions compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -893,11 +893,25 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
let item = tcx.hir_expect_item(def_id);

let (constness, is_alias, is_auto, safety) = match item.kind {
hir::ItemKind::Trait(constness, is_auto, safety, ..) => {
(constness, false, is_auto == hir::IsAuto::Yes, safety)
}
hir::ItemKind::TraitAlias(constness, ..) => (constness, true, false, hir::Safety::Safe),
let (constness, is_alias, is_auto, safety, impl_restriction) = match item.kind {
hir::ItemKind::Trait(constness, is_auto, safety, impl_restriction, ..) => (
constness,
false,
is_auto == hir::IsAuto::Yes,
safety,
if let hir::RestrictionKind::Restricted(path) = impl_restriction.kind {
ty::trait_def::ImplRestrictionKind::Restricted(path.res, impl_restriction.span)
} else {
ty::trait_def::ImplRestrictionKind::Unrestricted
},
),
hir::ItemKind::TraitAlias(constness, ..) => (
constness,
true,
false,
hir::Safety::Safe,
ty::trait_def::ImplRestrictionKind::Unrestricted,
),
_ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"),
};

Expand Down Expand Up @@ -946,6 +960,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
def_id: def_id.to_def_id(),
safety,
constness,
impl_restriction,
paren_sugar,
has_auto_impl: is_auto,
is_marker,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/collect/predicates_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
Some(ty::Binder::dummy(tcx.impl_trait_ref(def_id).instantiate_identity()));
}
}
ItemKind::Trait(_, _, _, _, _, self_bounds, ..)
ItemKind::Trait(_, _, _, _, _, _, self_bounds, ..)
| ItemKind::TraitAlias(_, _, _, self_bounds) => {
is_trait = Some((self_bounds, item.span));
}
Expand Down Expand Up @@ -1033,7 +1033,7 @@ pub(super) fn const_conditions<'tcx>(
Node::Item(item) => match item.kind {
hir::ItemKind::Impl(impl_) => (impl_.generics, None, false),
hir::ItemKind::Fn { generics, .. } => (generics, None, false),
hir::ItemKind::Trait(_, _, _, _, generics, supertraits, _) => {
hir::ItemKind::Trait(_, _, _, _, _, generics, supertraits, _) => {
(generics, Some((Some(item.owner_id.def_id), supertraits)), false)
}
hir::ItemKind::TraitAlias(_, _, generics, supertraits) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
| hir::ItemKind::Enum(_, generics, _)
| hir::ItemKind::Struct(_, generics, _)
| hir::ItemKind::Union(_, generics, _)
| hir::ItemKind::Trait(_, _, _, _, generics, ..)
| hir::ItemKind::Trait(_, _, _, _, _, generics, ..)
| hir::ItemKind::TraitAlias(_, _, generics, ..)
| hir::ItemKind::Impl(hir::Impl { generics, .. }) => {
// These kinds of items have only early-bound lifetime parameters.
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_hir_analysis/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1027,6 +1027,16 @@ pub(crate) struct SpecializationTrait {
pub span: Span,
}

#[derive(Diagnostic)]
#[diag("trait cannot be implemented outside `{$restriction_path}`")]
pub(crate) struct ImplOfRestrictedTrait {
#[primary_span]
pub impl_span: Span,
#[note("trait restricted here")]
pub restriction_span: Span,
pub restriction_path: String,
}

#[derive(Diagnostic)]
#[diag("implicit types in closure signatures are forbidden when `for<...>` is present")]
pub(crate) struct ClosureImplicitHrtb {
Expand Down
14 changes: 14 additions & 0 deletions compiler/rustc_hir_pretty/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,7 @@ impl<'a> State<'a> {
constness,
is_auto,
safety,
impl_restriction,
ident,
generics,
bounds,
Expand All @@ -770,6 +771,7 @@ impl<'a> State<'a> {
self.print_constness(constness);
self.print_is_auto(is_auto);
self.print_safety(safety);
self.print_impl_restriction(impl_restriction);
self.word_nbsp("trait");
self.print_ident(ident);
self.print_generic_params(generics.params);
Expand Down Expand Up @@ -2645,6 +2647,18 @@ impl<'a> State<'a> {
hir::IsAuto::No => {}
}
}

fn print_impl_restriction(&mut self, r: &hir::ImplRestriction<'_>) {
match r.kind {
hir::RestrictionKind::Unrestricted => {}
hir::RestrictionKind::Restricted(path) => {
self.word("impl(");
self.word_nbsp("in");
self.print_path(path, false);
self.word(")");
}
}
}
}

/// Does this expression require a semicolon to be treated
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1889,7 +1889,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Some(
Node::Item(hir::Item {
kind:
hir::ItemKind::Trait(_, _, _, ident, ..)
hir::ItemKind::Trait(_, _, _, _, ident, ..)
| hir::ItemKind::TraitAlias(_, ident, ..),
..
})
Expand Down Expand Up @@ -4533,7 +4533,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return;
}
Node::Item(hir::Item {
kind: hir::ItemKind::Trait(_, _, _, ident, _, bounds, _),
kind: hir::ItemKind::Trait(_, _, _, _, ident, _, bounds, _),
..
}) => {
let (sp, sep, article) = if bounds.is_empty() {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable {
let def_id = item.owner_id.to_def_id();
// NOTE(nbdd0121): use `dyn_compatibility_violations` instead of `is_dyn_compatible` because
// the latter will report `where_clause_object_safety` lint.
if let hir::ItemKind::Trait(_, _, _, ident, ..) = item.kind
if let hir::ItemKind::Trait(_, _, _, _, ident, ..) = item.kind
&& cx.tcx.is_dyn_compatible(def_id)
{
let direct_super_traits_iter = cx
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/hir/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -945,7 +945,7 @@ impl<'tcx> TyCtxt<'tcx> {
}) => until_within(*outer_span, ty.span),
// With generics and bounds.
Node::Item(Item {
kind: ItemKind::Trait(_, _, _, _, generics, bounds, _),
kind: ItemKind::Trait(_, _, _, _, _, generics, bounds, _),
span: outer_span,
..
})
Expand Down
Loading
Loading