@@ -948,6 +948,14 @@ impl<'db> KnownClass {
948948 }
949949 }
950950
951+ /// Lookup a [`KnownClass`] in typeshed and return a [`Type`]
952+ /// representing all possible instances of the class.
953+ ///
954+ /// ## Panics
955+ ///
956+ /// This method will panic if the class cannot be found in typeshed
957+ /// and *either* the `test` feature *or* the `debug_assertions` feature is enabled.
958+ /// See [`KnownClass::to_class_literal`] for more details.
951959 pub ( crate ) fn to_instance ( self , db : & ' db dyn Db ) -> Type < ' db > {
952960 self . to_class_literal ( db)
953961 . into_class_literal ( )
@@ -972,6 +980,44 @@ impl<'db> KnownClass {
972980 }
973981 }
974982
983+ /// Lookup a [`KnownClass`] in typeshed and return a [`Type`] representing that class-literal.
984+ ///
985+ /// ## Invariants upheld by this method
986+ ///
987+ /// When executed outside of tests, this method should never panic: if the symbol cannot
988+ /// be found in typeshed, the method simply returns [`Type::unknown()`].
989+ /// When executed in the context of tests, however, this method panics rather than falling
990+ /// back to `Unknown` if a symbol cannot be found.
991+ ///
992+ /// This means that two desirable properties are upheld:
993+ /// 1. red-knot works on (nearly) arbitrary custom typesheds without panicking when run
994+ /// outside of our tests. This is a potentially useful feature for a variety of reasons.
995+ /// 2. Implicit behaviour is kept to a minimum in the context of our tests.
996+ /// If [`KnownClass`] symbols silently fell back to `Unknown` in the context of a test
997+ /// that used a custom typeshed directory, it might lead to hard-to-debug test failures
998+ /// and confusing behaviour.
999+ ///
1000+ /// ## When this method panics
1001+ ///
1002+ /// This method panics if both the following conditions are met:
1003+ /// 1. Either no symbol can be found for the class in typeshed,
1004+ /// OR the found symbol is not a class definition,
1005+ /// OR the found symbol is possibly unbound.
1006+ /// 2. Either the `test` feature is enabled,
1007+ /// OR the `debug_assertions` feature is enabled.
1008+ ///
1009+ /// If condition (1) is met but condition (2) is not, we simply log a debug warning
1010+ /// and fall back to `Unknown`.
1011+ ///
1012+ /// ## Why do we panic if *either* `test` *or* `debug_assertions` is enabled?
1013+ ///
1014+ /// Some of our tests are not run in a context where the `test` feature is enabled
1015+ /// (for example, mdtests). Meanwhile, other tests are never run in our CI with
1016+ /// `debug_assertions` enabled, because running them with a debug build would take too
1017+ /// long (our property tests). For both of these tests, however, we want to avoid
1018+ /// special-cases symbols silently falling back to `Unknown`. Panicking if *either*
1019+ /// `test` is enabled *or* `debug_assertions` is enabled covers both cases, while still
1020+ /// avoiding panicking when red-knot is run on production code.
9751021 pub ( crate ) fn to_class_literal ( self , db : & ' db dyn Db ) -> Type < ' db > {
9761022 // a cache of the `KnownClass`es that we have already failed to lookup in typeshed
9771023 // (and therefore that we've already logged a warning for)
@@ -1010,6 +1056,14 @@ impl<'db> KnownClass {
10101056 } )
10111057 }
10121058
1059+ /// Lookup a [`KnownClass`] in typeshed and return a [`Type`]
1060+ /// representing that class and all possible subclasses of the class.
1061+ ///
1062+ /// ## Panics
1063+ ///
1064+ /// This method will panic if the class cannot be found in typeshed
1065+ /// and *either* the `test` feature *or* the `debug_assertions` feature is enabled.
1066+ /// See [`KnownClass::to_class_literal`] for more details.
10131067 pub ( crate ) fn to_subclass_of ( self , db : & ' db dyn Db ) -> Type < ' db > {
10141068 self . to_class_literal ( db)
10151069 . into_class_literal ( )
0 commit comments