Skip to content

Commit 1e584d2

Browse files
add suggestion when there is a impl of external trait on pointer
Signed-off-by: Vincenzo Palazzo <[email protected]>
1 parent 2643b16 commit 1e584d2

File tree

3 files changed

+92
-1
lines changed

3 files changed

+92
-1
lines changed

compiler/rustc_typeck/src/coherence/orphan.rs

+36-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
44
use rustc_data_structures::fx::FxHashSet;
55
use rustc_errors::struct_span_err;
6-
use rustc_errors::ErrorGuaranteed;
6+
use rustc_errors::{Diagnostic, ErrorGuaranteed};
77
use rustc_hir as hir;
88
use rustc_infer::infer::TyCtxtInferExt;
99
use rustc_middle::ty::subst::GenericArgKind;
@@ -107,6 +107,7 @@ fn do_orphan_check_impl<'tcx>(
107107
Err(err) => emit_orphan_check_error(
108108
tcx,
109109
sp,
110+
item.span,
110111
tr.path.span,
111112
trait_ref.self_ty(),
112113
impl_.self_ty.span,
@@ -207,6 +208,7 @@ fn do_orphan_check_impl<'tcx>(
207208
fn emit_orphan_check_error<'tcx>(
208209
tcx: TyCtxt<'tcx>,
209210
sp: Span,
211+
full_impl_span: Span,
210212
trait_span: Span,
211213
self_ty: Ty<'tcx>,
212214
self_ty_span: Span,
@@ -247,8 +249,20 @@ fn emit_orphan_check_error<'tcx>(
247249
ty::Slice(_) => (this, " because slices are always foreign"),
248250
ty::Array(..) => (this, " because arrays are always foreign"),
249251
ty::Tuple(..) => (this, " because tuples are always foreign"),
252+
ty::RawPtr(ptr_ty) => {
253+
emit_newtype_suggestion_for_raw_ptr(
254+
full_impl_span,
255+
self_ty,
256+
self_ty_span,
257+
ptr_ty,
258+
&mut err,
259+
);
260+
261+
(format!("`{}`", ty), " because raw pointers are always foreign")
262+
}
250263
_ => (format!("`{}`", ty), ""),
251264
};
265+
252266
let msg = format!("{} is not defined in the current crate{}", ty, postfix);
253267
if *is_target_ty {
254268
// Point at `D<A>` in `impl<A, B> for C<B> in D<A>`
@@ -330,6 +344,27 @@ fn emit_orphan_check_error<'tcx>(
330344
})
331345
}
332346

347+
fn emit_newtype_suggestion_for_raw_ptr(
348+
full_impl_span: Span,
349+
self_ty: Ty<'_>,
350+
self_ty_span: Span,
351+
ptr_ty: &ty::TypeAndMut<'_>,
352+
diag: &mut Diagnostic,
353+
) {
354+
if !self_ty.needs_subst() {
355+
let mut_key = if ptr_ty.mutbl == rustc_middle::mir::Mutability::Mut { "mut " } else { "" };
356+
let msg_sugg = "consider introducing a new wrapper type".to_owned();
357+
let sugg = vec![
358+
(
359+
full_impl_span.shrink_to_lo(),
360+
format!("struct WrapperType(*{}{});\n\n", mut_key, ptr_ty.ty),
361+
),
362+
(self_ty_span, "WrapperType".to_owned()),
363+
];
364+
diag.multipart_suggestion(msg_sugg, sugg, rustc_errors::Applicability::MaybeIncorrect);
365+
}
366+
}
367+
333368
/// Lint impls of auto traits if they are likely to have
334369
/// unsound or surprising effects on auto impls.
335370
fn lint_auto_trait_impl<'tcx>(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Emit additional suggestion to correct the trait implementation
2+
// on a pointer
3+
use std::{fmt, marker};
4+
5+
struct LocalType;
6+
7+
impl fmt::Display for *mut LocalType {
8+
//~^ ERROR only traits defined in the current crate can be implemented for arbitrary types
9+
//~| NOTE impl doesn't use only types from inside the current crate
10+
//~| NOTE `*mut LocalType` is not defined in the current crate because raw pointers are always foreign
11+
//~| NOTE define and implement a trait or new type instead
12+
//~| HELP consider introducing a new wrapper type
13+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
14+
write!(f, "This not compile")
15+
}
16+
}
17+
18+
impl<T> marker::Copy for *mut T {
19+
//~^ ERROR only traits defined in the current crate can be implemented for arbitrary types
20+
//~| NOTE impl doesn't use only types from inside the current crate
21+
//~| NOTE `*mut T` is not defined in the current crate because raw pointers are always foreign
22+
//~| NOTE define and implement a trait or new type instead
23+
}
24+
25+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
2+
--> $DIR/issue-99572-impl-trait-on-pointer.rs:7:1
3+
|
4+
LL | impl fmt::Display for *mut LocalType {
5+
| ^^^^^^^^^^^^^^^^^^^^^^--------------
6+
| | |
7+
| | `*mut LocalType` is not defined in the current crate because raw pointers are always foreign
8+
| impl doesn't use only types from inside the current crate
9+
|
10+
= note: define and implement a trait or new type instead
11+
help: consider introducing a new wrapper type
12+
|
13+
LL + struct WrapperType(*mut LocalType);
14+
LL +
15+
LL ~ impl fmt::Display for WrapperType {
16+
|
17+
18+
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
19+
--> $DIR/issue-99572-impl-trait-on-pointer.rs:18:1
20+
|
21+
LL | impl<T> marker::Copy for *mut T {
22+
| ^^^^^^^^^^^^^^^^^^^^^^^^^------
23+
| | |
24+
| | `*mut T` is not defined in the current crate because raw pointers are always foreign
25+
| impl doesn't use only types from inside the current crate
26+
|
27+
= note: define and implement a trait or new type instead
28+
29+
error: aborting due to 2 previous errors
30+
31+
For more information about this error, try `rustc --explain E0117`.

0 commit comments

Comments
 (0)