Skip to content

add #![rustc_no_implicit_bounds] #142671

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
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
4 changes: 4 additions & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1108,6 +1108,10 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
TEST, rustc_insignificant_dtor, Normal, template!(Word),
WarnFollowing, EncodeCrossCrate::Yes
),
rustc_attr!(
TEST, rustc_no_implicit_bounds, CrateLevel, template!(Word),
WarnFollowing, EncodeCrossCrate::No
),
rustc_attr!(
TEST, rustc_strict_coherence, Normal, template!(Word),
WarnFollowing, EncodeCrossCrate::Yes
Expand Down
20 changes: 11 additions & 9 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ use rustc_errors::codes::*;
use rustc_errors::struct_span_code_err;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
use rustc_hir::{AmbigArg, LangItem, PolyTraitRef};
use rustc_middle::bug;
use rustc_middle::ty::{
self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
TypeVisitor, Upcast,
};
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw};
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym};
use rustc_trait_selection::traits;
use smallvec::SmallVec;
use tracing::{debug, instrument};
Expand Down Expand Up @@ -188,6 +188,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
) {
let tcx = self.tcx();

// Skip adding any default bounds if `#![rustc_no_implicit_bounds]`
if tcx.has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) {
return;
}

let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span);
let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);

Expand Down Expand Up @@ -408,24 +413,21 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let tcx = self.tcx();
let trait_id = tcx.lang_items().get(trait_);
if let Some(trait_id) = trait_id
&& self.do_not_provide_default_trait_bound(
trait_id,
hir_bounds,
self_ty_where_predicates,
)
&& self.should_add_default_traits(trait_id, hir_bounds, self_ty_where_predicates)
{
add_trait_bound(tcx, bounds, self_ty, trait_id, span);
}
}

fn do_not_provide_default_trait_bound<'a>(
/// Returns `true` if default trait bound should be added.
fn should_add_default_traits<'a>(
&self,
trait_def_id: DefId,
hir_bounds: &'a [hir::GenericBound<'tcx>],
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
) -> bool {
let collected = collect_bounds(hir_bounds, self_ty_where_predicates, trait_def_id);
!collected.any()
!self.tcx().has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) && !collected.any()
}

/// Lower HIR bounds into `bounds` given the self type `param_ty` and the overarching late-bound vars if any.
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1866,6 +1866,7 @@ symbols! {
rustc_never_returns_null_ptr,
rustc_never_type_options,
rustc_no_implicit_autorefs,
rustc_no_implicit_bounds,
rustc_no_mir_inline,
rustc_nonnull_optimization_guaranteed,
rustc_nounwind,
Expand Down
10 changes: 7 additions & 3 deletions tests/ui/cast/cast-rfc0401-vtable-kinds.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
//@ run-pass

#![feature(rustc_attrs)]
#![rustc_no_implicit_bounds]

Comment on lines +2 to +5
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for unsize coercions/trait object coercions test, the attribute makes them a bit confusing/harder to read for me 🤔

so maybe only limit the attribute to tests for the trait solver 🤔

// Check that you can cast between different pointers to trait objects
// whose vtable have the same kind (both lengths, or both trait pointers).

Expand All @@ -9,11 +13,11 @@ trait Bar { //~ WARN trait `Bar` is never used
impl Bar for () {}

#[repr(C)]
struct FooS<T:?Sized>(T);
struct FooS<T>(T);
#[repr(C)]
struct BarS<T:?Sized>(T);
struct BarS<T>(T);

fn foo_to_bar<T:?Sized>(u: *const FooS<T>) -> *const BarS<T> {
fn foo_to_bar<T>(u: *const FooS<T>) -> *const BarS<T> {
u as *const BarS<T>
}

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/cast/cast-rfc0401-vtable-kinds.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
warning: trait `Bar` is never used
--> $DIR/cast-rfc0401-vtable-kinds.rs:5:7
--> $DIR/cast-rfc0401-vtable-kinds.rs:9:7
|
LL | trait Bar {
| ^^^
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: lifetime may not live long enough
--> $DIR/ptr-to-trait-obj-different-regions-id-trait.rs:24:27
--> $DIR/ptr-to-trait-obj-different-regions-id-trait.rs:26:27
|
LL | fn m<'a>() {
| -- lifetime `'a` defined here
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: lifetime may not live long enough
--> $DIR/ptr-to-trait-obj-different-regions-id-trait.rs:24:27
--> $DIR/ptr-to-trait-obj-different-regions-id-trait.rs:26:27
|
LL | fn m<'a>() {
| -- lifetime `'a` defined here
Expand Down
10 changes: 6 additions & 4 deletions tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,22 @@
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
//@ check-fail
//
#![feature(rustc_attrs)]
#![rustc_no_implicit_bounds]

// Make sure we can't trick the compiler by using a projection.

trait Cat<'a> {}
impl Cat<'_> for () {}

trait Id {
type Id: ?Sized;
type Id;
}
impl<T: ?Sized> Id for T {
impl<T> Id for T {
type Id = T;
}

struct S<T: ?Sized> {
struct S<T> {
tail: <T as Id>::Id,
}

Expand Down
8 changes: 5 additions & 3 deletions tests/ui/coercion/codegen-smart-pointer-with-alias.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,22 @@
// system, which isn't guaranteed to be normalized after substitution.

#![feature(coerce_unsized)]
#![feature(rustc_attrs)]
#![rustc_no_implicit_bounds]

use std::ops::CoerceUnsized;

trait Mirror {
type Assoc: ?Sized;
type Assoc;
}
impl<T: ?Sized> Mirror for T {
impl<T> Mirror for T {
type Assoc = T;
}

trait Any {}
impl<T> Any for T {}

struct Signal<'a, T: ?Sized>(<&'a T as Mirror>::Assoc);
struct Signal<'a, T>(<&'a T as Mirror>::Assoc);

// This `CoerceUnsized` impl isn't special; it's a bit more restricted than we'd see in the wild,
// but this ICE also reproduces if we were to make it general over `Signal<T> -> Signal<U>`.
Expand Down
6 changes: 4 additions & 2 deletions tests/ui/coercion/issue-26905-rpass.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
//@ run-pass
#![feature(unsize, coerce_unsized)]
#![feature(rustc_attrs)]
#![rustc_no_implicit_bounds]

// Verfies that PhantomData is ignored for DST coercions

use std::marker::{Unsize, PhantomData};
use std::ops::CoerceUnsized;

struct MyRc<T: ?Sized> {
struct MyRc<T> {
_ptr: *const T,
_boo: PhantomData<T>,
}

impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<MyRc<U>> for MyRc<T>{ }
impl<T: Unsize<U>, U> CoerceUnsized<MyRc<U>> for MyRc<T>{ }

fn main() {
let data = [1, 2, 3];
Expand Down
8 changes: 5 additions & 3 deletions tests/ui/coercion/issue-26905.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
#![feature(unsize, coerce_unsized)]
#![feature(rustc_attrs)]
#![rustc_no_implicit_bounds]

// Verfies that non-PhantomData ZSTs still cause coercions to fail.
// They might have additional semantics that we don't want to bulldoze.

use std::marker::{Unsize, PhantomData};
use std::ops::CoerceUnsized;

struct NotPhantomData<T: ?Sized>(PhantomData<T>);
struct NotPhantomData<T>(PhantomData<T>);

struct MyRc<T: ?Sized> {
struct MyRc<T> {
_ptr: *const T,
_boo: NotPhantomData<T>,
}

impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<MyRc<U>> for MyRc<T>{ } //~ERROR
impl<T: Unsize<U>, U> CoerceUnsized<MyRc<U>> for MyRc<T>{ } //~ERROR

fn main() {
let data = [1, 2, 3];
Expand Down
8 changes: 4 additions & 4 deletions tests/ui/coercion/issue-26905.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error[E0375]: implementing `CoerceUnsized` does not allow multiple fields to be coerced
--> $DIR/issue-26905.rs:16:40
--> $DIR/issue-26905.rs:18:23
|
LL | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<MyRc<U>> for MyRc<T>{ }
| ^^^^^^^^^^^^^^^^^^^^^^
LL | impl<T: Unsize<U>, U> CoerceUnsized<MyRc<U>> for MyRc<T>{ }
| ^^^^^^^^^^^^^^^^^^^^^^
|
note: the trait `CoerceUnsized` may only be implemented when a single field is being coerced
--> $DIR/issue-26905.rs:12:5
--> $DIR/issue-26905.rs:14:5
|
LL | _ptr: *const T,
| ^^^^^^^^^^^^^^
Expand Down
4 changes: 3 additions & 1 deletion tests/ui/coercion/sub-principals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
// a non-higer-ranked instantiation.

#![feature(unsize)]
#![feature(rustc_attrs)]
#![rustc_no_implicit_bounds]

use std::marker::Unsize;

fn test<T: ?Sized, U: ?Sized>()
fn test<T, U>()
where
T: Unsize<U>,
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
error: conflicting implementations of trait `FnMarker` for type `fn(&_)`
--> $DIR/negative-coherence-placeholder-region-constraints-on-unification.rs:21:1
--> $DIR/negative-coherence-placeholder-region-constraints-on-unification.rs:23:1
|
LL | impl<T: ?Sized + Marker> FnMarker for fn(T) {}
| ------------------------------------------- first implementation here
LL | impl<T: ?Sized> FnMarker for fn(&T) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `fn(&_)`
LL | impl<T: Marker> FnMarker for fn(T) {}
| ---------------------------------- first implementation here
LL | impl<T> FnMarker for fn(&T) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `fn(&_)`
|
= warning: the behavior may change in a future release
= note: for more information, see issue #56105 <https://github.com/rust-lang/rust/issues/56105>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,24 @@

#![forbid(coherence_leak_check)]
#![feature(negative_impls, with_negative_coherence)]
#![feature(rustc_attrs)]
#![rustc_no_implicit_bounds]

pub trait Marker {}

#[cfg(implicit)]
impl<T: ?Sized> !Marker for &T {}
impl<T> !Marker for &T {}

#[cfg(explicit)]
impl<'a, T: ?Sized + 'a> !Marker for &'a T {}
impl<'a, T: 'a> !Marker for &'a T {}

trait FnMarker {}

// Unifying these two impls below results in a `T: '!0` obligation
// that we shouldn't need to care about. Ideally, we'd treat that
// as an assumption when proving `&'!0 T: Marker`...
impl<T: ?Sized + Marker> FnMarker for fn(T) {}
impl<T: ?Sized> FnMarker for fn(&T) {}
impl<T: Marker> FnMarker for fn(T) {}
impl<T> FnMarker for fn(&T) {}
//[explicit]~^ ERROR conflicting implementations of trait `FnMarker` for type `fn(&_)`
//[explicit]~| WARN the behavior may change in a future release

Expand Down
8 changes: 5 additions & 3 deletions tests/ui/const-generics/issues/issue-88119.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
//@ compile-flags: -Znext-solver
#![allow(incomplete_features)]
#![feature(const_trait_impl, generic_const_exprs)]
#![feature(rustc_attrs)]
#![rustc_no_implicit_bounds]

#[const_trait]
trait ConstName {
Expand All @@ -12,18 +14,18 @@ impl const ConstName for u8 {
const NAME_BYTES: &'static [u8] = b"u8";
}

const fn name_len<T: ?Sized + ConstName>() -> usize {
const fn name_len<T: ConstName>() -> usize {
T::NAME_BYTES.len()
}

impl<T: ?Sized + ConstName> const ConstName for &T
impl<T: ConstName> const ConstName for &T
where
[(); name_len::<T>()]:,
{
const NAME_BYTES: &'static [u8] = b"&T";
}

impl<T: ?Sized + ConstName> const ConstName for &mut T
impl<T: ConstName> const ConstName for &mut T
where
[(); name_len::<T>()]:,
{
Expand Down
Loading
Loading