Unsized coercion in the method call

use std::ops::Deref;

struct Foo<T:?Sized>(T);
trait MyTrait{
	fn show(&self);
}
impl MyTrait for i32{
	fn show(&self){}
}
trait Method{
	fn method(&self);
}
impl Method for Foo<dyn MyTrait>{  
	fn method(&self) {  // #1
		
	}
}
impl Method for i32{
	fn method(&self) {
		println!("for i32");
	}
}
static GLOBAL:[i32;1] = [0];
impl Deref for Foo<i32>{
    type Target = [i32;1];

    fn deref(&self) -> &Self::Target {
       //&self.0
	   &GLOBAL
    }
}
/*
impl Method for [i32]{
	fn method(&self) {
		println!("for [i32]");
	}
}
*/
fn main(){
	let r1:&Foo<dyn MyTrait>  = &Foo(0);
	let r = Foo(0);
	r.method();
}

In this example, r.method won't find the method at #1. Method call expressions - The Rust Reference says:

The first step is to build a list of candidate receiver types. Obtain these by repeatedly dereferencing the receiver expression's type, adding each type encountered to the list, then finally attempting an unsized coercion at the end, and adding the result type if that is successful.

So, I wonder whether the unsized coercion in a method call only applies to the last type that results from the dereferenced types?

That's a long-standing inaccuracy in the reference. Only slice unsizing[1] happens as part of method resolution. Unsizing to dyn Trait does not happen.


  1. perhaps including custom slice-based DSTs, or perhaps not, I can't remember offhand ↩ī¸Ž

3 Likes

So, the issue is actually this: Which types does the unsized coercion apply to when the method is looked up?

This says only array to slice, but I don't have time back that up via testing right now.

3 Likes