1

In this dart snippet:

// The value 'null' can't be returned from a function with return type 'T' 
// because 'T' is not nullable.
T func1<T>() {
  return null;
}

void func2<T>(T x) {
  print(x);
}
  
void main() {
  String? s = func1();
  func2(null);
}

Both functions use generic T; one tries to treat T as nullable within the function body and fails, the other's caller tries to treat T as nullable and succeeds. I understand the second one, but I am confused by this difference. In both cases, I would argue that T should be nullable because dart docs says that the default type is T extends Object?. The error remains the same even if I change the func1's signature to make T inherit explicitly from nullable object using func1<T extends Object?>.

I can get it to compile by changing the return type to T?, but then why would the docs say that the default is T extends Object?. Is this requirement to specify the type as T? before you can return null just a syntax rule to make it clear to the callers that the return value may be null?

If that is the case, dart allows me to override that rule; even if I keep the return type as T, I can get func1 to return null by changing it to return null as T;. And it runs fine because after all, T extends Object?. This kinda breaks the expectation that a generic function with return type T may not return null. The following code compiles fine, but throws a runtime error as T resolves to String during runtime causing the casting to fail. I understand why that's happening, but why isn't there a way to catch this at compile time?


T func3<T>() {
  return null as T;
}

  
void main() {
  String s = func3();
}

I am sure I am missing something basic about generic functions, and/or how they should be implemented in dart. But I couldn't find any official documentation other than the one I linked. So any input regarding this would be much appreciated.

0

1 Answer 1

1

It's not a rule that T extends object? infers that T will be T?.

No it will be just non-nullable T, except for the parameters of type T they could be T?.

You must explicitly mark the return type as T? even if it implicitly exetends Object?

So, for your example:

You should mark the return type as T? Although it extends Object?

T? func1 <T>(){
  
  return null;
}

and if you have a parameter that may be null, it can accept null because T extends Object? by default. but not the return type (you explicitly make it nullable).

T? func1 <T>(T a){ // a could be passed as nullable or non-nullable
  
  return null;
}

void main() {

  var a = func1(null);
  print(a);
  
}
Sign up to request clarification or add additional context in comments.

5 Comments

var a = func1(null); <-- In this statement, what type is inferred for T?
@Dai , passing a null will be acceptable because T extends Object? by default. so the parametrized generic a can accept null as T? although it's of T type.
@Dai the type Null would be inferred for T.
I understand it, but couldn't find any official documentation regarding this anywhere. Also, being able to return null as T from a generic function of type T kind of defeats the purpose of having to "explicitly make the return type nullable with T?"
@Amarghosh i will answer you by asking a question. null as T casting is done successfully because T extends Object? ok ? but if i'm asking you what is the return type of this function, is it T or T?, as a client for that function i don't care about being T extends some nullable or not, so nullability of the return type is stated explicitly to clarify method signature to clients.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.