+# A type prefixed with "nullable"
+class MNullableType
+ super MProxyType
+
+ init
+ do
+ self.to_s = "nullable {mtype}"
+ end
+
+ redef var to_s: String is noinit
+
+ redef var full_name is lazy do return "nullable {mtype.full_name}"
+
+ redef var c_name is lazy do return "nullable__{mtype.c_name}"
+
+ redef fun as_nullable do return self
+ redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
+ do
+ var res = super
+ return res.as_nullable
+ end
+
+ # Efficiently returns `mtype.lookup_fixed(mmodule, resolved_receiver).as_nullable`
+ redef fun lookup_fixed(mmodule, resolved_receiver)
+ do
+ var t = super
+ if t == mtype then return self
+ return t.as_nullable
+ end
+end
+
+# A non-null version of a formal type.
+#
+# When a formal type in bounded to a nullable type, this is the type of the not null version of it.
+class MNotNullType
+ super MProxyType
+
+ redef fun to_s do return "not null {mtype}"
+ redef var full_name is lazy do return "not null {mtype.full_name}"
+ redef var c_name is lazy do return "notnull__{mtype.c_name}"
+
+ redef fun as_notnull do return self
+
+ redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
+ do
+ var res = super
+ return res.as_notnull
+ end
+
+ # Efficiently returns `mtype.lookup_fixed(mmodule, resolved_receiver).as_notnull`
+ redef fun lookup_fixed(mmodule, resolved_receiver)
+ do
+ var t = super
+ if t == mtype then return self
+ return t.as_notnull
+ end
+end
+