Skip to content

Commit 6c37252

Browse files
committed
permit negative impls for non-auto traits
1 parent 3c6f982 commit 6c37252

33 files changed

+304
-85
lines changed

src/libcore/clone.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,4 +227,9 @@ mod impls {
227227
*self
228228
}
229229
}
230+
231+
// Shared references can be cloned, but mutable references *cannot*!
232+
#[stable(feature = "rust1", since = "1.0.0")]
233+
#[cfg(not(bootstrap))]
234+
impl<T: ?Sized> !Clone for &mut T {}
230235
}

src/libcore/ops/deref.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ impl<T: ?Sized> Deref for &T {
8181
}
8282
}
8383

84+
#[cfg(not(bootstrap))]
85+
#[stable(feature = "rust1", since = "1.0.0")]
86+
impl<T: ?Sized> !DerefMut for &T {}
87+
8488
#[stable(feature = "rust1", since = "1.0.0")]
8589
impl<T: ?Sized> Deref for &mut T {
8690
type Target = T;

src/librustc_error_codes/error_codes.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@ E0184: include_str!("./error_codes/E0184.md"),
9797
E0185: include_str!("./error_codes/E0185.md"),
9898
E0186: include_str!("./error_codes/E0186.md"),
9999
E0191: include_str!("./error_codes/E0191.md"),
100-
E0192: include_str!("./error_codes/E0192.md"),
101100
E0193: include_str!("./error_codes/E0193.md"),
102101
E0195: include_str!("./error_codes/E0195.md"),
103102
E0197: include_str!("./error_codes/E0197.md"),
@@ -424,6 +423,8 @@ E0745: include_str!("./error_codes/E0745.md"),
424423
E0746: include_str!("./error_codes/E0746.md"),
425424
E0747: include_str!("./error_codes/E0747.md"),
426425
E0748: include_str!("./error_codes/E0748.md"),
426+
E0749: include_str!("./error_codes/E0749.md"),
427+
E0750: include_str!("./error_codes/E0750.md"),
427428
;
428429
// E0006, // merged with E0005
429430
// E0008, // cannot bind by-move into a pattern guard
@@ -458,6 +459,7 @@ E0748: include_str!("./error_codes/E0748.md"),
458459
// E0188, // can not cast an immutable reference to a mutable pointer
459460
// E0189, // deprecated: can only cast a boxed pointer to a boxed object
460461
// E0190, // deprecated: can only cast a &-pointer to an &-object
462+
// E0192, // negative impl only applicable to auto traits
461463
// E0194, // merged into E0403
462464
// E0196, // cannot determine a type for this closure
463465
E0208,
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Negative impls are not allowed to have any items. Negative impls
2+
declare that a trait is **not** implemented (and never will be) and
3+
hence there is no need to specify the values for trait methods or
4+
other items.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Negative impls cannot be default impls. A default impl supplies
2+
default values for the items within to be used by other impls, whereas
3+
a negative impl declares that there are no other impls. These don't
4+
make sense to combine.

src/librustc_typeck/check/mod.rs

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1656,11 +1656,14 @@ fn check_opaque_for_inheriting_lifetimes(tcx: TyCtxt<'tcx>, def_id: DefId, span:
16561656
_ => unreachable!(),
16571657
};
16581658

1659-
tcx.sess.span_err(span, &format!(
1659+
tcx.sess.span_err(
1660+
span,
1661+
&format!(
16601662
"`{}` return type cannot contain a projection or `Self` that references lifetimes from \
16611663
a parent scope",
16621664
if is_async { "async fn" } else { "impl Trait" },
1663-
));
1665+
),
1666+
);
16641667
}
16651668
}
16661669

@@ -1838,8 +1841,8 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: DefId, span: Span)
18381841
Ok(ConstValue::ByRef { alloc, .. }) => {
18391842
if alloc.relocations().len() != 0 {
18401843
let msg = "statics with a custom `#[link_section]` must be a \
1841-
simple list of bytes on the wasm target with no \
1842-
extra levels of indirection such as references";
1844+
simple list of bytes on the wasm target with no \
1845+
extra levels of indirection such as references";
18431846
tcx.sess.span_err(span, msg);
18441847
}
18451848
}
@@ -1968,6 +1971,24 @@ fn check_impl_items_against_trait<'tcx>(
19681971
return;
19691972
}
19701973

1974+
// Negative impls are not expected to have any items
1975+
match tcx.impl_polarity(impl_id) {
1976+
ty::ImplPolarity::Reservation | ty::ImplPolarity::Positive => {}
1977+
ty::ImplPolarity::Negative => {
1978+
if !impl_item_refs.is_empty() {
1979+
let first_item_span = tcx.hir().impl_item(impl_item_refs[0].id).span;
1980+
struct_span_err!(
1981+
tcx.sess,
1982+
first_item_span,
1983+
E0749,
1984+
"negative impls cannot have any items"
1985+
)
1986+
.emit();
1987+
}
1988+
return;
1989+
}
1990+
}
1991+
19711992
// Locate trait definition and items
19721993
let trait_def = tcx.trait_def(impl_trait_ref.def_id);
19731994

@@ -2007,7 +2028,7 @@ fn check_impl_items_against_trait<'tcx>(
20072028
impl_item.span,
20082029
E0323,
20092030
"item `{}` is an associated const, \
2010-
which doesn't match its trait `{}`",
2031+
which doesn't match its trait `{}`",
20112032
ty_impl_item.ident,
20122033
impl_trait_ref.print_only_trait_path()
20132034
);
@@ -3555,7 +3576,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
35553576
let adjusted_ty = autoderef.unambiguous_final_ty(self);
35563577
debug!(
35573578
"try_index_step(expr={:?}, base_expr={:?}, adjusted_ty={:?}, \
3558-
index_ty={:?})",
3579+
index_ty={:?})",
35593580
expr, base_expr, adjusted_ty, index_ty
35603581
);
35613582

@@ -4708,7 +4729,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
47084729
err.span_label(
47094730
fn_span,
47104731
"implicitly returns `()` as its body has no tail or `return` \
4711-
expression",
4732+
expression",
47124733
);
47134734
}
47144735
},
@@ -5593,11 +5614,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
55935614
match self.at(&self.misc(span), self.param_env).sup(impl_ty, self_ty) {
55945615
Ok(ok) => self.register_infer_ok_obligations(ok),
55955616
Err(_) => {
5596-
self.tcx.sess.delay_span_bug(span, &format!(
5617+
self.tcx.sess.delay_span_bug(
5618+
span,
5619+
&format!(
55975620
"instantiate_value_path: (UFCS) {:?} was a subtype of {:?} but now is not?",
55985621
self_ty,
55995622
impl_ty,
5600-
));
5623+
),
5624+
);
56015625
}
56025626
}
56035627
}
@@ -5783,7 +5807,7 @@ fn fatally_break_rust(sess: &Session) {
57835807
handler.note_without_error("the compiler expectedly panicked. this is a feature.");
57845808
handler.note_without_error(
57855809
"we would appreciate a joke overview: \
5786-
https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675",
5810+
https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675",
57875811
);
57885812
handler.note_without_error(&format!(
57895813
"rustc {} running on {}",

src/librustc_typeck/check/wfcheck.rs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -112,15 +112,14 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: DefId) {
112112
}
113113
ty::ImplPolarity::Negative => {
114114
// FIXME(#27579): what amount of WF checking do we need for neg impls?
115-
if of_trait.is_some() && !is_auto {
115+
if let hir::Defaultness::Default { .. } = defaultness {
116116
struct_span_err!(
117117
tcx.sess,
118118
item.span,
119-
E0192,
120-
"negative impls are only allowed for \
121-
auto traits (e.g., `Send` and `Sync`)"
119+
E0750,
120+
"negative impls cannot be default impls"
122121
)
123-
.emit()
122+
.emit();
124123
}
125124
}
126125
ty::ImplPolarity::Reservation => {
@@ -886,13 +885,13 @@ fn check_opaque_types<'fcx, 'tcx>(
886885
.struct_span_err(
887886
span,
888887
"non-defining opaque type use \
889-
in defining scope",
888+
in defining scope",
890889
)
891890
.span_label(
892891
param_span,
893892
"cannot use static lifetime; use a bound lifetime \
894-
instead or remove the lifetime parameter from the \
895-
opaque type",
893+
instead or remove the lifetime parameter from the \
894+
opaque type",
896895
)
897896
.emit();
898897
} else {
@@ -907,13 +906,13 @@ fn check_opaque_types<'fcx, 'tcx>(
907906
.struct_span_err(
908907
span,
909908
"non-defining opaque type use \
910-
in defining scope",
909+
in defining scope",
911910
)
912911
.span_note(
913912
tcx.def_span(param.def_id),
914913
&format!(
915914
"used non-generic const {} for \
916-
generic parameter",
915+
generic parameter",
917916
ty,
918917
),
919918
)
@@ -928,7 +927,7 @@ fn check_opaque_types<'fcx, 'tcx>(
928927
.struct_span_err(
929928
span,
930929
"non-defining opaque type use \
931-
in defining scope",
930+
in defining scope",
932931
)
933932
.span_note(spans, "lifetime used multiple times")
934933
.emit();
@@ -1014,7 +1013,7 @@ fn check_method_receiver<'fcx, 'tcx>(
10141013
span,
10151014
&format!(
10161015
"`{}` cannot be used as the type of `self` without \
1017-
the `arbitrary_self_types` feature",
1016+
the `arbitrary_self_types` feature",
10181017
receiver_ty,
10191018
),
10201019
)

src/test/ui/error-codes/E0192.rs

Lines changed: 0 additions & 12 deletions
This file was deleted.

src/test/ui/error-codes/E0192.stderr

Lines changed: 0 additions & 9 deletions
This file was deleted.

src/test/ui/specialization/defaultimpl/validation.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ default impl S {} //~ ERROR inherent impls cannot be `default`
88

99
default unsafe impl Send for S {} //~ ERROR impls of auto traits cannot be default
1010
default impl !Send for Z {} //~ ERROR impls of auto traits cannot be default
11+
//~^ ERROR negative impls cannot be default impls
1112

1213
trait Tr {}
13-
default impl !Tr for S {} //~ ERROR negative impls are only allowed for auto traits
14+
default impl !Tr for S {} //~ ERROR negative impls cannot be default impls
1415

1516
fn main() {}

0 commit comments

Comments
 (0)